Redis缓存

121 阅读3分钟

Redis作为缓存和数据库的区别

  • 缓存数据"不重要",可以丢,追求极速
  • 缓存不是全量数据
  • 缓存随着访问而变化(热数据)
  • 数据库:数据不能丢失,除了速度之外还有持久性。

缓存常见问题

  • 击穿
    某个key在DB中存在,但刚好在缓存中失效(过期等原因),突然大量请求访问该key,请求全都到达了DB,相当于在缓存上开了个口,造成DB压力,压垮DB。
    解决方案: 1. 互斥锁,针对某一热点数据,在获取时通过互斥锁保证只有一个请求到达DB,该请求访问到后把结果放进缓存。

  • 穿透 请求缓存和DB中压根不存在的数据,使每次请求访问DB,给DB带来压力。
    解决方案: 1. client中增加redis的key-value标记,标记不存在,即布隆过滤器 2. 数据增加了元素,必须要完成对布隆的增加 3. 可能是攻击者,封禁IP

  • 雪崩 大量keys过期失效,导致客户端请求都直接到达DB。
    解决方案: 1. 设置随机缓存过期事件,让key过期事件均匀分布。 2. 不设置缓存过期时间。 3. 分布式缓存中,将热点数据放进不同的缓存服务器。

  • 一致性 缓存和DB中数据的一致性问题,当我们需要修改或删除数据时,即要操作数据库的数据,也要操作redis的数据。缓存与数据库一致性问题无法统一,只能通过一些措施降低不一致问题的概率。
    删除还是更新?

    当存储的数据发生变化时,Redis也要更新,我们> 有两种方案:一是直接更新redis数据再set到DB,另一种是世界删除redis数据,下次查询时在写入redis。
    当在更新缓存前,如果还要经过其他表的查询、接口调用、计算才能得到最新的数据,而不是直接从数据库拿到值,那么直接删除redis缓存中的值。
    而在一般情况下也推荐先删除的方案。

    先更新DB还是先删除缓存?

    • 先更新数据库在删除缓存
      正常情况:更新数据库成功 -> 删除缓存
      异常情况:
      1.更新数据库异常 -> 程序不会走到下一步,数据不会出现不一致
      2.更新数据库成功 删除缓存失败 -> 出现数据不一致
    • 先删除缓存再更新数据库
      异常情况: 删除缓存成功,数据库更新失败。-> 因为以数据库的数据为准,不会出现数据不一致的情况。
      看起来没有问题,但是当出现并发情况时,会出现问题,当clientA删除redis中的key1,准备更新DB时,clientB又查询了key1,重新写入到了redis中。
      解决方案:双删策略,在更新数据库后再删一次。

布隆过滤器

过滤请求, 用类似bitmap(二进制hash地址)的方法快速过滤判定数据库是否也存在数据。概率解决问题,不可能100%阻挡。请求也可能被错误阻挡,但是会大量阻挡。 且成本低、速度快。
实现方式:

  • 客户端自己实现布隆过滤器,自己承载bitmap,redis仅作为缓存
  • 或者redis中集成承载布隆过滤器