聊聊Elasticsearch的SingleObjectCache
阿新 • • 發佈:2019-06-09
序
本文主要研究一下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值