缓存穿透、雪崩、击穿、一致性

  • 缓存穿透
    1. 对一个不存在的数据进行请求,该请求会直接穿透缓存,到数据库查询,数据库中也没有。当并发查不存在的数据时,大量请求到达数据库,给数据库造成很大压力。
    2. 解决方案:
      1. 过滤请求: 接口层增加校验 如id校验 若id<=0 直接拦截
      2. 布隆过滤器

        布隆过滤器可以判断某个数据不存在 或 可能存在

        方法:k个hash函数将key散列成k个整数;设置长度为n的比特数组 初始时都为0;对已存在的数据 也就是已有的key 用k个hash函数计算出k个散列值,比特数组中对应的位置置1;查询是否存在时,若k个散列值有一个为0则不存在,全为1则可能存在

        将可能查询的key 存入布隆过滤器,用户查询时 发现不存在 则直接丢弃 不对持久层查询

        问题: 布隆过滤器不支持删除

      3. 缓存空对象

          1.   持久层不命中时,将空对象缓存起来,并设置短过期时间(避免占用资源)

        2. 问题:缓冲空值占用空间,因为要缓存具有空值的键;即使设置过期时间,也存在缓存层与持久化层时间窗口不一致,影响保持一致性的业务

  • 缓存雪崩
    1. 大量请求到达数据库,由于1数据未被加载到缓存;2缓存在同一时间大面积失效;3缓存服务器宕机
    2. 解决方案
      1. 进行缓存预热(提前将数据加载到缓存,避免在请求时先查询数据库),避免系统刚启动不久还未将大量数据进行缓存时导致的雪崩
      2. 观察用户行为,合理设置缓存过期时间;在默认的缓存时间上加随机1-5分钟;避免同一时间大面积过期导致的雪崩
      3. 分布式缓存,每个节点只缓存部分数据,某节点宕机后其他节点的缓存仍可用;避免缓存服务器宕机造成的雪崩
  • 缓冲击穿
    1. 请求未缓冲但数据库中存在的数据,由于高并发,同时在缓存中未读到数据,又同时去数据库取数据,引起数据库压力瞬间增大
    2. 与缓冲雪崩的区别:击穿指的是并发到数据库查同一条数据;雪崩是指并发到服务器查许多条数据
    3. 解决方案:
      1. 使用互斥锁 mutex key
        1. 使用Redis中的SETNX( set if not exists):若缓存失效,不立即冲数据库查找,而是设置一个互斥锁,设置成功再去数据库查找,否则延迟一小段时间再重新尝试从缓存中获取
        2. Memcache的add
      2. 提前使用互斥锁
        1. 在value内部设置一个超时值t2,t2比实际的超时值小,当从缓存中读到该数据,发现t2已经过期时,加互斥锁,延长t2并重新读入缓存。

           3. 永不过期

        •   不设置过期时间,不会出现热点key过期问题
        •   不过期就成静态的了,所以将过期时间存再key对应的value里,发现快过期时,使用后台的异步线程进行缓存的构建

           4. 资源保护:资源隔离组件 hystrix

  • 缓存一致性
    1. 数据更新的同时 缓存也能实时更新
    2. 方案:
      1. 数据更新的同时立即更新缓存
      2. 读缓存时 判断缓存是否最新
    3. 最好缓存对一致性要求不高的数据 且允许缓存存在脏数据
    4. 缓存更新策略:https://blog.csdn.net/W_317/article/details/114261969
      1. Cache aside: 先更新数据库 再删除缓存;设置缓存时间 保证数据一致性
      2. Read/write through :Cache Provider对外提供读写操作 应用程序不用感知操作的是缓存还是数据
      3. Write behind: 延迟写入 Cache Provider 每隔一段时间 批量写入数据库,写入快 适用于频繁写,但缓冲和数据库不是强一致性

 

posted @ 2021-09-12 16:38  lancelee98  阅读(110)  评论(0编辑  收藏  举报