视频参考黑马的Redis教程

缓存穿透

缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到数据库

如果放任这种请求不断访问,就很容易搞垮数据库T_T,于是有了两种常见的解决方案

缓存空对象

  • 思路:缓存空对象到Redis中,这样下次再请求就不会到达数据库
  • 优点:
    • 实现简单,维护方便
  • 缺点:
    • 额外的内存消耗
    • 可能造成短期的不一致

      常见的解决办法就是为null设置TTL(有效时间),避免存太多了null垃圾

  • 业务中实现流程:
    1. 在数据库查询为空的时候向Redis添加空值,并设置TTL
    2. Redis请求时对空值做判断

布隆过滤

  • 思路:在客户端与Redis之间再加入一层布隆过滤器,如果不存在数据,直接拒绝请求返回,有才继续
    • 布隆过滤器:基于某种哈希算法去计算出数据对应的hash值,再转换为二进制保存到布隆过滤器中
    • 所以布隆过滤器可以看作一个二进制的数组,而布隆过滤实际是一种算法
  • 优点:
    • 内存占用较少,没有多余的key
  • 缺点:
    • 实现复杂
    • 存在误判的可能

      这里可以看出布隆过滤器借助了哈希,也就意味着不存在时真不存在,但布隆过滤器查询存在时并非一定存在,还是有击穿的风险

非常见方案(主动)

  • 增加id的复杂度,避免被猜测id规律
  • 做好数据的基础格式的校验
  • 加强用户权限校验
  • 做好热点参数的限流(TO DO见springcloud)

缓存雪崩

缓存雪崩是指在同意时段大量的缓存key同时失效或者Redis服务宕机,导致大量的请求到达数据库,带来巨大压力

解决方案

  • 给不同的Key的TTL添加随机值
  • 利用Redis集群提高服务的可用性
  • 给缓存业务添加降级限流策略
  • 给业务添加多级缓存

缓存击穿

缓存击穿问题也叫热点Key问题,就是一个被高并发访问并且缓存重建业务较复杂的key突然失效了,无数的请求访问会在瞬间给数据库带来巨大的冲击

互斥锁

  • 悲观锁的机制,参考我的另一篇文章乐观锁、悲观锁
  • 优点:
    • 没有额外的内存消耗
    • 保持一致性
    • 实现简单
  • 缺点:
    • 线程需要等待,性能受到影响
    • 可能会有死锁的风险

逻辑过期

  • 思路:不设置TTL,设置逻辑过期(例如在value中添加一个expire),过期后获取到互斥锁,会开启到新的线程去操作写入缓存,重置逻辑过期时间,同时返回旧数据
  • 优点:
    • 线程无需等待,性能较好
  • 缺点
    • 不保持一致性
    • 有额外的内存消耗
    • 实现复杂