Skip to the content.

首页

缓存常见的问题


一、缓存一致性

更新数据时需要保证缓存和数据库的数据一致性。

一般来说,缓存有以下三种模式:

Read/Write Through

Write Behind

只操作缓存,由缓存服务自己更新数据库,与 Read/Write Through 模式区别是更新操作为非同步

Cache Aside

一般场景下使用的模式,同一个操作内更新缓存和数据库。

  1. 先更新缓存,再更新数据库。

    违背了隔离性原则,写操作数据还未持久化其他读操作就可以读取到该写操作对数据的更改。

  2. 先更新数据库,再更新缓存。

    数据库事务回滚问题:缓存操作执行成功但是响应超时抛出异常,或者服务器宕机来不及提交事务,都会导致数据库回滚但缓存更新成功,出现不一致

    并发写问题:如果允许并发更新操作,可能数据库先更新的反而后更新缓存,数据库后更新的反而先更新缓存,出现不一致

  3. 先删除缓存,再更新数据库。

    并发读写问题:读操作在写操作删除缓存之后更新数据库之前读取到旧的数据并加载缓存,出现不一致。

  4. (推荐)先更新数据库,再删除缓存。

    并发读写问题:读操作在写操作之前读取到旧的数据,并在写操作完成之后加载缓存,可能出现不一致,但是概率极低,因为写操作耗时一般大大超过读操作耗时,可以视为不会出现不一致。

    主从同步延迟问题写操作完成之后但数据库主从同步完成前,读操作从从库读取到旧数据并加载缓存,出现不一致。

延时双删

先删除缓存,再更新数据库,延迟一段时间再次删除缓存。

延时的目的是为了等待并发读操作加载缓存完毕之后再删去不一致的缓存,延迟时间的确定是关键,太长会导致数据不一致的中间态时间过长,太短则可能出现不一致。

延时删除可以通过监听binlog,结合DelayQueue、WheelTimer或延时消息等实现。


二、缓存雪崩

大量的缓存在同一个时刻过期,缓存雪崩也会导致缓存击穿

解决方案:


三、缓存击穿(缓存并发)

大量的请求访问某个缓存失效或不存在缓存的key,会导致大量请求查询数据库和更新缓存。

解决方案:


四、缓存穿透

大量请求访问缓存和数据库都不存在的key。

解决方案:


五、缓存热key

热点分散:分布式缓存服务器中某些key是访问的热点,导致热点key所属节点承载的压力比其他节点大很多。

突发热点:某段时间内某些key会成为访问的热点,导致缓存服务器也无法承受。


六、缓存大key

解决方案:

大key删除:如果直接删除会长时间阻塞服务器,应该限制每次删除的数量,使用命令:hash(hscan)、set(sscan)、list(ltrim)、zset(zremrangebyrank)。Redis4.0开始支持Lazy Free,主动或被动删除的键会在后台线程中处理,主动删除使用UNLINK命令,被动删除需要开启对应的配置


七、缓存抖动

分布式缓存中某个节点突然发生故障导致该节点缓存不可用。

解决方案:


八、熔断限流保护

系统可用性最后的壁垒,在设计缓存系统时一定要考虑好所有异常情况,同时对缓存服务器及数据库都要使用某种熔断限流保护措施。


九、多级缓存

多层级缓存可以有效提高整个系统的缓存查询效率和缓存组件的可用性,但缓存一致性问题的处理则更加复杂。一般方案是将本地内存作为一级缓存,全局缓存作为二级缓存,本地缓存查询不到则查询全局缓存最后才加载缓存,缓存淘汰时通过集群广播的方式通知所有服务器实例淘汰本地缓存。