目录
缓存雪崩
解决方案:
缓存击穿
解决方案
缓存雪崩
缓存雪崩是指在同一时段大量的缓存key同时失效或者Redis服务宕机,导致大量请求到达数据库,带来巨大压力。
解决方案:
u 给不同的 Key 的 TTL 添加随机值
u 利用 Redis 集群提高服务的可用性
u 给缓存业务添加降级限流策略
u 给业务添加多级缓存
缓存击穿
缓存击穿问题也叫热点Key问题,就是一个被高并发访问并且缓存重建业务较复杂的key突然失效了,无数的请求访问会在瞬间给数据库带来巨大的冲击。
解决方案
1.互斥锁
2.逻辑过期
互斥锁和逻辑回归的优缺点
互斥锁:
优点:
• 没有额外的内存消耗• 保证一致性• 实现简单缺点:
• 线程需要等待,性能受影响• 可能有死锁风险
逻辑回归:
优点:
• 线程无需等待,性能较好缺点:
• 不保证一致性• 有额外内存消耗• 实现复杂
使用互斥锁的形式解决缓存击穿
public Shop queryWithMutex(Long id) throws InterruptedException {String key = CACHE_SHOP_KEY + id;//1.从redis中查询店铺缓存String jsonShop = stringRedisTemplate.opsForValue().get(key);//2.判断是否存在if (StrUtil.isNotBlank(jsonShop)) {//3.存在,直接返回return JSONUtil.toBean(jsonShop, Shop.class);}if ("".equals(jsonShop)) {return null;}//4.不存在,重建缓存//4.1 获取互斥锁//shop为实体类Shop shop = null;try {Boolean isLock = tryLock(LOCK_SHOP_KEY + id);//4.2 判断是否获取成功if (!isLock) {//4.3 失败,则休眠并重试Thread.sleep(50);return queryWithPassThrough(id);}//4.4 成功,根据id查询数据库shop = getById(id);//5. 不存在 返回错误if (shop == null) {// 将空值放入redisstringRedisTemplate.opsForValue().set(key, "", CACHE_NULL_TTL, TimeUnit.MINUTES);return null;}// 6. 存在 写入 redisstringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(shop), CACHE_SHOP_TTL, TimeUnit.MINUTES);} catch (InterruptedException e) {throw new RuntimeException(e);} finally {//7.释放互斥锁unLock(LOCK_SHOP_KEY + id);}//8.返回return shop;}