
com.netflix.evcache.EVCacheInMemoryCache Maven / Gradle / Ivy
The newest version!
package com.netflix.evcache;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
import com.netflix.archaius.api.Property;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Optional;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.CacheStats;
import com.google.common.cache.LoadingCache;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListenableFutureTask;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.netflix.evcache.metrics.EVCacheMetricsFactory;
import com.netflix.evcache.util.EVCacheConfig;
import com.netflix.spectator.api.BasicTag;
import com.netflix.spectator.api.Counter;
import com.netflix.spectator.api.Gauge;
import com.netflix.spectator.api.Id;
import com.netflix.spectator.api.Tag;
import net.spy.memcached.transcoders.Transcoder;
/**
* An In Memory cache that can be used to hold data for short duration. This is
* helpful when the same key is repeatedly requested from EVCache within a short
* duration. This can be turned on dynamically and can relive pressure on
* EVCache Server instances.
*/
public class EVCacheInMemoryCache {
private static final Logger log = LoggerFactory.getLogger(EVCacheInMemoryCache.class);
private final Property _cacheDuration; // The key will be cached for this long
private final Property _refreshDuration, _exireAfterAccessDuration;
private final Property _cacheSize; // This many items will be cached
private final Property _poolSize; // This many threads will be initialized to fetch data from evcache async
private final String appName;
private final Map counterMap = new ConcurrentHashMap();
private final Map gaugeMap = new ConcurrentHashMap();
private LoadingCache> cache;
private ExecutorService pool = null;
private final Transcoder tc;
private final EVCacheImpl impl;
private final Id sizeId;
public EVCacheInMemoryCache(String appName, Transcoder tc, EVCacheImpl impl) {
this.appName = appName;
this.tc = tc;
this.impl = impl;
this._cacheDuration = EVCacheConfig.getInstance().getPropertyRepository().get(appName + ".inmemory.expire.after.write.duration.ms", Integer.class).orElseGet(appName + ".inmemory.cache.duration.ms").orElse(0);
this._cacheDuration.subscribe((i) -> setupCache());
this._exireAfterAccessDuration = EVCacheConfig.getInstance().getPropertyRepository().get(appName + ".inmemory.expire.after.access.duration.ms", Integer.class).orElse(0);
this._exireAfterAccessDuration.subscribe((i) -> setupCache());;
this._refreshDuration = EVCacheConfig.getInstance().getPropertyRepository().get(appName + ".inmemory.refresh.after.write.duration.ms", Integer.class).orElse(0);
this._refreshDuration.subscribe((i) -> setupCache());
this._cacheSize = EVCacheConfig.getInstance().getPropertyRepository().get(appName + ".inmemory.cache.size", Integer.class).orElse(100);
this._cacheSize.subscribe((i) -> setupCache());
this._poolSize = EVCacheConfig.getInstance().getPropertyRepository().get(appName + ".thread.pool.size", Integer.class).orElse(5);
this._poolSize.subscribe((i) -> initRefreshPool());
final List tags = new ArrayList(3);
tags.addAll(impl.getTags());
tags.add(new BasicTag(EVCacheMetricsFactory.METRIC, "size"));
this.sizeId = EVCacheMetricsFactory.getInstance().getId(EVCacheMetricsFactory.IN_MEMORY, tags);
setupCache();
setupMonitoring(appName);
}
private WriteLock writeLock = new ReentrantReadWriteLock().writeLock();
private void initRefreshPool() {
final ExecutorService oldPool = pool;
writeLock.lock();
try {
final ThreadFactory factory = new ThreadFactoryBuilder().setDaemon(true).setNameFormat(
"EVCacheInMemoryCache-%d").build();
pool = Executors.newFixedThreadPool(_poolSize.get(), factory);
if(oldPool != null) oldPool.shutdown();
} finally {
writeLock.unlock();
}
}
private void setupCache() {
try {
CacheBuilder
© 2015 - 2025 Weber Informatics LLC | Privacy Policy