缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到数据库。
1. 缓存空对象 优点:实现简单,维护方便 缺点:额外内存消耗,可能造成短期的不一致 步骤:对于不存在key,我们缓存2分钟空对象
2. 布隆过滤 优点:内存占用较少,没有多余key 缺点:实现复杂,存在误判可能 步骤:通过布隆过滤器,确定对象是否存在
缓存空对象流程图:
@GetMapping("/{id}")
public Result queryShopById(@PathVariable("id") Long id) {
Shop shop;
// 1. 查询redis缓存
String str_shop = stringRedisTemplate.opsForValue().get(CACHE_SHOP_KEY + id);
// 2. 判断是否存在,如果存在走缓存
if (StrUtil.isNotBlank(str_shop)) {
System.out.println("go cache " + id);
shop = JSONUtil.toBean(str_shop, Shop.class);
return Result.ok(shop);
}
// 6. 不存在,但是如果是空字符串,防止缓存穿透
if("".equals(str_shop)) {
return Result.fail("店铺不存在");
}
// 3. 不存在从数据库查询
shop = shopService.getById(id);
if(shop == null) {
// 5. 防止缓存穿透
stringRedisTemplate.opsForValue().set(CACHE_SHOP_KEY + id, "", CACHE_NULL_TTL, TimeUnit.MINUTES);
return Result.fail("店铺不存在");
}
// 4. 在放到缓存中去
str_shop = JSONUtil.toJsonStr(shop);
stringRedisTemplate.opsForValue().set(CACHE_SHOP_KEY + id, str_shop, CACHE_SHOP_TTL, TimeUnit.MINUTES);
return Result.ok(shop);
}
<aside> 💡 如果数据库不存在,防止缓存穿透设置对应的value为空 查找时,如果value是空,直接返回数据
</aside>
用户请求的数据在缓存中和数据库中都不存在,不断发起这样的请求,给数据库带来巨大压力
缓存null值 布隆过滤 增强id的复杂度,避免被猜测id规律 做好数据的基础格式校验 加强用户权限校验 做好热点参数的限流
缓存雪崩是指在同一时段大量的缓存key同时失效或者Redis服务宕机,导致大量请求到达数据库,带来巨大压力。
解决方案: