本文主要研究一下Elasticsearch的SingleObjectCache

SingleObjectCache

elasticsearch-7.0.1/server/src/main/java/org/elasticsearch/common/util/SingleObjectCache.java

public abstract class SingleObjectCache<T>{    private volatile T cached;    private Lock refreshLock = new ReentrantLock();    private final TimeValue refreshInterval;    protected long lastRefreshTimestamp = 0;    protected SingleObjectCache(TimeValue refreshInterval, T initialValue) {        if (initialValue == null) {            throw new IllegalArgumentException("initialValue must not be null");        }        this.refreshInterval = refreshInterval;        cached = initialValue;    }    /**     * Returns the currently cached object and potentially refreshes the cache before returning.     */    public T getOrRefresh() {        if (needsRefresh()) {            if(refreshLock.tryLock()) {                try {                    if (needsRefresh()) { // check again!                        cached = refresh();                        assert cached != null;                        lastRefreshTimestamp = System.currentTimeMillis();                    }                } finally {                    refreshLock.unlock();                }            }        }        assert cached != null;        return cached;    }    /** Return the potentially stale cached entry. */    protected final T getNoRefresh() {        return cached;    }    /**     * Returns a new instance to cache     */    protected abstract T refresh();    /**     * Returns <code>true</code> iff the cache needs to be refreshed.     */    protected boolean needsRefresh() {        if (refreshInterval.millis() == 0) {            return true;        }        final long currentTime = System.currentTimeMillis();        return (currentTime - lastRefreshTimestamp) > refreshInterval.millis();    }}
  • SingleObjectCache的构造器要求refreshInterval、initialValue两个参数;它提供了getOrRefresh方法,该方法会判断该cached值是否过期,如果过期则调用refresh方法刷新值,同时更新lastRefreshTimestamp,如果没过期则返回cached值

实例

elasticsearch-7.0.1/server/src/main/java/org/elasticsearch/monitor/fs/FsService.java

public class FsService {    private static final Logger logger = LogManager.getLogger(FsService.class);    private final FsProbe probe;    private final TimeValue refreshInterval;    private final SingleObjectCache<FsInfo> cache;    private final ClusterInfoService clusterInfoService;    public static final Setting<TimeValue> REFRESH_INTERVAL_SETTING =        Setting.timeSetting(            "monitor.fs.refresh_interval",            TimeValue.timeValueSeconds(1),            TimeValue.timeValueSeconds(1),            Property.NodeScope);    public FsService(final Settings settings, final NodeEnvironment nodeEnvironment, ClusterInfoService clusterInfoService) {        this.probe = new FsProbe(nodeEnvironment);        this.clusterInfoService = clusterInfoService;        refreshInterval = REFRESH_INTERVAL_SETTING.get(settings);        logger.debug("using refresh_interval [{}]", refreshInterval);        cache = new FsInfoCache(refreshInterval, stats(probe, null, logger, null));    }    public FsInfo stats() {        return cache.getOrRefresh();    }    private static FsInfo stats(FsProbe probe, FsInfo initialValue, Logger logger, @Nullable ClusterInfo clusterInfo) {        try {            return probe.stats(initialValue, clusterInfo);        } catch (IOException e) {            logger.debug("unexpected exception reading filesystem info", e);            return null;        }    }    private class FsInfoCache extends SingleObjectCache<FsInfo> {        private final FsInfo initialValue;        FsInfoCache(TimeValue interval, FsInfo initialValue) {            super(interval, initialValue);            this.initialValue = initialValue;        }        @Override        protected FsInfo refresh() {            return stats(probe, initialValue, logger, clusterInfoService.getClusterInfo());        }    }}
  • FsService的构造器使用FsInfoCache创建了cache,其无参的stats方法执行的是cache.getOrRefresh();FsInfoCache继承了SingleObjectCache,它的refresh方法调用的是stats方法,该方法通过probe.stats(initialValue, clusterInfo)来刷新值

小结

SingleObjectCache的构造器要求refreshInterval、initialValue两个参数;它提供了getOrRefresh方法,该方法会判断该cached值是否过期,如果过期则调用refresh方法刷新值,同时更新lastRefreshTimestamp,如果没过期则返回cached值

doc

  • SingleObjectCache