序
本文主要研究一下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值
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。