获取缓存时处理缓存穿透

处理多线程获取缓存时由于缓存过期而引发缓存穿透的问题。

实际应用遇到的应用场景:

1.redis缓存的数据过期时从DB中获取最新数据以刷新缓存,当多个线程同时到达缓存过期时刻,会同时刷新缓存,该场景下就需要实现仅有一个线程调用DB(通过对象锁,加双重判断),否则会消耗过多的DB连接资源(严重的使DB崩掉)。

2.系统间调用时,请求数据中通常包含token信息,而token会过期失效,这与1中类型,也要在token失效后重新获取,与刷新缓存类似。


package com.eplusing.cache;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
public class CacheTmplateService {
private Map client;
public <T> T findCache(String key, Date expire, TypeReference<T> clazz, LoadCallback<T> load){
String json = client.get(key) + "";
if (StringUtils.isBlank(json) || json.equalsIgnoreCase("null")) {
//所有的线程只要等待在这里的都将去数据库查
synchronized (this) {
json = client.get(key) + "";
if (StringUtils.isBlank(json) || json.equalsIgnoreCase("null")) {
//模拟缓存没找到去数据库查找花费的时间
T t = load.load();

client.set(key, json, expire);

return t;
}
return JSON.parseObject(json, clazz);
}
}else{
return JSON.parseObject(json, clazz);
}
}
}

猜你喜欢

转载自blog.csdn.net/cpp1781089410/article/details/80274253