Redis缓存问题


Redis 作为缓存应用在各种大型项目中,但在实际开发中不得不考虑许多常见问题

一 缓存穿透

1. 问题描述

如果查询一个系统根本不存在的数据,缓存层和数据库均不会命中,从而导致每次请求都要到持久层数据库查询,从而失去了缓存的意义,同时也给攻击者留下后门,增大系统风险。

这可能是业务代码或数据自身问题导致,也不能排除恶意攻击。

2. 解决方案

  • 缓存空对象

当持久层不命中后,即使返回的空对象也将其缓存起来,同时会设置一个过期时间,之后再访问这个数据将会从缓存中获取,保护了后端数据源。

适用于数据频繁变换且实时性高的场景,代码上实现简单,需要额外开销,且存在数据不一致的问题。

  • 接口层校验

通常使用布隆过滤器(Bloom Filter)实现,适用于数据固定的场景,其优势是节约空间,但维护复杂。

二 缓存击穿

1. 问题描述

热点数据的并发量很大,缓存失效后会导致大量请求直接指向持久层,造成数据的压力瞬间增大。

2. 解决方案

  • 热点数据永不过期

但无法保证数据的一致性,且增大维护成本。

  • 互斥锁

当缓存未命中数据,则由第一个请求进入的线程获取到互斥锁,从数据库中获取数据,其余线程等待第一个线程释放锁后再从缓存中获取数据。

穿透 VS 击穿

  • 缓存穿透:缓存层和持久层均无数据
  • 缓存击穿:缓存层无数据但持久层有数据

三 缓存雪崩

1. 问题描述

大批量数据同时到期或者缓存层宕机,导致大批量流量直接打到持久层,增大数据库的压力。

2. 解决方案

  • 缓存时间随机或热点数据不过期
  • 缓存层分布式部署,提高可用性
  • 依赖隔离组件为后端存储限流并降级

击穿 VS 雪崩

  • 缓存击穿:针对同一条热点数据
  • 缓存雪崩:大批量同时到期数据

四 缓存无底洞

1. 问题描述

随着节点增加,一次批量操作可能会设计多次网络请求一访问多个节点,导致耗时不降反增。

2. 解决方案

  • 串行 mget

将 mget 操作(n 个 key)拆分为逐次执行 N 次 get 操作。

  • 串行 IO

对批量操作中的 key 值按节点分类归档,然后逐次进行 mget 操作。

  • 并行 IO

将串行 IO 方案中的逐次操作改为多线程并发操作。

  • hash-tag

可以将多个 key 值强制分配到同一个节点,但也会导致数据倾斜。

Reference


文章作者: Anosh
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Anosh !
 本篇
Redis缓存问题 Redis缓存问题
Redis 作为缓存应用在各种大型项目中,但在实际开发中不得不考虑许多常见问题 一 缓存穿透1. 问题描述如果查询一个系统根本不存在的数据,缓存层和数据库均不会命中,从而导致每次请求都要到持久层数据库查询,从而失去了缓存的意义,同时也给
下一篇 
面向对象的原则 面向对象的原则
对于面向对象语言而言,有“六原则,一法则”去遵循: 六原则 单一原则:一个类只应该做它该做的事情,做到高聚合,低耦合 开闭原则:开放拓展,关闭修改。既尽量从原有系统派生出新类,而避免直接对原系统的修改 依赖倒置原则:面向接口编程 里氏替换原
2020-07-26
  目录