缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到数据库。如果有不怀好意的人多线程故意发送错误的请求过来,这样每次错误的请求都会经过redis最终打到数据库上,给数据库带来压力

注意!
这里是空对象指的不是null,是“”
1.0版本
@Override
public Result queryById(Long id) {
String key = CACHE_SHOP_KEY + id;
// 1.从redis查询缓存
String shopJSON = stringRedisTemplate.opsForValue().get(key);
// 2.判断缓存中是否命中
// ""进不了这个if
if (StringUtils.isNotBlank(shopJSON)){
// 3.命中,返回缓存数据
Shop shop = JSONUtil.toBean(shopJSON, Shop.class);
return Result.ok(shop);
}
// 判断命中的是不是“”
if ("".equals(shopJSON)){
return Result.fail("该id不存在");
}
// 4.不存在,查询数据库
Shop shop = getById(id);
if (shop ==null){
// 空值缓存
stringRedisTemplate.opsForValue().set(key,"",CACHE_NULL_TTL,TimeUnit.MINUTES);
// 5.不存在,返回错误
return Result.fail("数据不存在");
}
// 6.数据库中存在,返回数据到controller,存储数据到缓存
stringRedisTemplate.opsForValue().set(key,JSONUtil.toJsonStr(shop),CACHE_SHOP_TTL, TimeUnit.MINUTES);
return Result.ok(shop);
}
2.0版本
/**
* 解决缓存穿透,空字符对象返回
* @param prefix
* @param id
* @param type
* @param function
* @param time
* @param unit
* @return
* @param <R>
* @param <ID>
*/
public <R,ID> R queryWithPassThrough(String prefix,ID id, Class<R> type, Function<ID,R> function, Long time, TimeUnit unit){
String key = prefix + id;
String JSON = stringRedisTemplate.opsForValue().get(key);
if (StringUtils.isNotBlank(JSON)){
return JSONUtil.toBean(JSON, type);
}
if ("".equals(JSON)){
return null;
}
/*
数据库查询
*/
R r = function.apply(id);
if (r ==null){
stringRedisTemplate.opsForValue().set(key,"",CACHE_NULL_TTL,TimeUnit.MINUTES);
return null;
}
this.set(prefix+id,r,time,unit);
return r;
}