序
本文主要研究一下Elasticsearch的SingleObjectCache
SingleObjectCache
elasticsearch-7.0.1/server/src/main/java/org/elasticsearch/common/util/SingleObjectCache.java
public abstract class SingleObjectCache{ 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 true
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 SingleObjectCachecache; private final ClusterInfoService clusterInfoService; public static final Setting 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 { 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值