文章目录
一、缓存穿透
1. 什么是缓存穿透
缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到数据库,给数据库带来压力
2. 解决方案
2.1 缓存空对象
思路:客户端请求Redis,请求未命中,请求数据库也未名中,这时直接将空对象缓存在Redis中
优点:实现简单,维护方便
缺点:额外的内存消耗(可以为其增加一个短期的TTL来解决)、可能造成短期的不一致(新增数据时,主动将数据插入缓存中,覆盖之前的null)
//缓存穿透
public Shop queryWithPassThrough(Long id){
//1.从redis查询商铺缓存
String key = CACHE_SHOP_KEY + id;
String shopJson = stringRedisTemplate.opsForValue().get(key);
//2.判断是否存在
if (StrUtil.isNotBlank(shopJson)) {
//3.存在,直接返回
return JSONUtil.toBean(shopJson, Shop.class);
}
//判断命中的是否是空值
if (shopJson != null) {
//返回错误信息
return null;
}
//4.不存在,根据id查询数据库,
Shop shop = getById(id);
//5.不存在,返回错误
if (shop == null) {
//将空值写入Redis
stringRedisTemplate.opsForValue().set(key, "", CACHE_NULL_TTL, TimeUnit.MINUTES);
return null;
}
//6.存在,写入redis
stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(shop), CACHE_SHOP_TTL, TimeUnit.MINUTES);
//7.返回
return shop;
}
2.2 布隆过滤
思路:在客户端和Redis之间添加布隆过滤器。当用户请求时,首先到布隆过滤器,如果数据不存在,直接拒绝。如果存在,则放行。
优点:内存占用较少,没有多余的key
缺点:实现复杂、存在误判可能
2.3 增加id的复杂度,避免被猜测id规律
2.4 做好数据的基础格式校验
2.5 加强用户权限校验
2.6 做好热点参数的限流
二、缓存雪崩
1. 什么是缓存雪崩
缓存雪崩是指在同一时间段大量的缓存key同时失效或者Redis服务宕机,导致大量请求到数据库,带来巨大压力
2. 解决方案
- 给不同的key的TTL添加随机值
- 利用Redis集群提高服务的可用性
- 给缓存业务添加降级限流策略
- 给业务添加多级缓存
三、缓存击穿
1. 什么是缓存击穿
也叫热点key问题,就是一个被高并发访问并且缓存重建业务较复杂的key突然失效了,无数的请求访问会在瞬间给数据库带来巨大的冲击
2. 解决方案
-
互斥锁:当一个请求查询缓存,未命中时,获取互斥锁成功,查询数据库重建缓存数据,写入缓存,释放锁。其他的线程查询缓存时,未命中,获取互斥锁失败,休眠一会重试,失败再重试,直到获取到互斥锁,查询到缓存。
//缓存击穿:互斥锁解决 public Shop queryWithMutex(Long id){ //1.从redis查询商铺缓存 String key = CACHE_SHOP_KEY + id; String shopJson = stringRedisTemplate.opsForValue().get(key); //2.判断是否存在 if (StrUtil.isNotBlank(shopJson)) { //3.存在,直接返回 return JSONUtil.toBean(shopJson, Shop.class); } //判断命中的是否是空值 if (shopJson !=