本地缓存初始化
public class LocalCacheInitService extends baseService{
@Override
public void afterPropertiesSet() throws Exception{
//商品类目缓存
Cache categoryCache =
CacheBuilder.newBuilder().softValues()
.maximumSize(1000000)
.expireAfterWrite(Switches.CATEGORY.getExpireInSeconds()/2,TimeUnit.SECONDS).build();
addCache(Switches.CATEGORY_KEY,categoryCache);
}
private void addCache(String key,Cache,?> cache){
localCacheService.addCache(key,cache);
}
}
写缓存封装
public void set(final String key,final Object value) throws RuntimeException{
if(value == null){
return;
}
//如果不复制的话,假设数据更改后造成本地缓存和分布式缓存不一致
final Object finalValue = copy(value);
//如果配置了写本地缓存,则根据key获得相关的本地缓存,然后写入
if(writableLocalCache){
Cache localCache = getLocalCache(key);
if(localCache != null){
localCache.put(key,finalValue);
}
}
//如果配置了不写分布式缓存,则直接返回
if(!writeRemoteCache){
return;
}
//异步更新分布式缓存
asyncTaskExecutor.execute(()->{
try{
redisCache.set(key,JSONUtils.toJSON(finalValue)
,remoteCacheExpiresInSeconds)
}catch(Exception e){
LOG.error("update redis cache error,key:{}",key,e);
}
});
}
读缓存API封装
private Map innerMget(List keys,List types) throws Exception{
Map result = Maps.newHashMap();
List missKeys = Lists.newArrayList();
List missTypes = Lists.newArrayList();
//如果配置了读本地缓存,则先读本地缓存
if(readLocalCache){
for(int i = 0;i< keys.size();i++){
String key = keys.get(i);
ClassType = types.get(i);
Cache localCache = getLocalCache(key);
if(localCache != null){
Object value = localCache.getIfPresent(key);
result.put(key,value);
if(value == null){
missKeys.add(key);
missTypes.add(type);
}
}else{
missKeys.add(key);
missTypes.add(type);
}
}
}
//如果配置了不读分布式缓存,则返回
if(!readRemoteCache){
return result;
}
final Map missResult = Maps.newHashMap();
//分区,批量执行
final List> keysPage = Lists.partition(missKeys,10);
List>> pageFutures = Lists.newArrayList();
try{
//获取批量数据
for(final List partitionKeys:keysPage){
pageFutures.add(asyncTaskExecutor.submit(
()->redisCache.mget(patitionKeys)
));
}
for(Future
空对象的定义
private static final String NULL_STRING = new String();
String value = loadDB();
if(value == null){
value = NULL_STRING;
}
myCache.put(id,value);
//读取数据时,如果发现NULL对象,不回源到DB,直接返回null
value = suitCache.getIfPresent(id);
if(value == NULL_STRING){
return null;
}
强制获取最新数据
if(ForceUpdater.isForceUpdateMyInfo()){
myCache.refresh(skuId);
}
String result = myCache.get(skuId);
if(result == NULL_STRING){
return null;
}
失败统计
private LoadingCache failedCache = CacheBuilder.newBuilder().softValue()
.maximumSize(10000).build(
new cacheLoader(){
@Override
public AtomicInteger load(String skuId) throws Exception{
return new AtomicInteger(0);
}
}
)
延迟报警
private static LoadingCache alarmCache = CacheBuilder.newBuilder()
.softValues().maximumSize(10000).expireAfterAccess(1,TimeUnit.HOURS).build(
new CacheLoader(){
@Override
public Integer load() throws Exception{
return 0;
}
}
);
Integer count = 0;
if(redis != null){
String countStr = Objects.firstNonNull(resis.opsForValue().get(key),"0");
count = Integer.valueOf(countStr);
}else{
count = alarmCache.get(key);
}
if(count%5 ==0){
//报警
}
count = count + 1;
if(resis != null){
resis.opsForValue().set(key,String.valueOf(count),TimeUnit.HOURS);
}else{
alarmCache.put(key,count);
}