对于缓存的更新,目前主要有两种策略
2023年12月18日大约 2 分钟缓存Cache
对于缓存的更新,目前主要有两种策略
缓存一致性问题往往发生在
MySQL
和Redis
中
在数据变更过程中,因为并发、系统故障等问题导致数据、缓存更新不一致
缓存更新策略
对于缓存的更新,目前主要有两种策略
超时剔除策略
适用于低一致性需求,很少发生变更的数据
比方说将数据存在 Redis
中,并设置 ttl
读请求到来时发现数据过期后,重新去 MySQL
中查询并塞入缓存
主动更新策略
适用于高一致性需求,常发生变更的数据
超时剔除作为兜底
数据发生变更后,主动发起对缓存的修改(更新或删除),可以通过异步线程、MQ 等方式
操作类型
读操作(读缓存)
缓存命中,直接返回
缓存未命中,查库然后更新缓存
写操作(写缓存)
更新缓存?删除缓存?
肯定是选择删除缓存!先删除缓存,后更新数据库
会存在并发场景下更新数据后依旧读取老数据的问题
可以使用延迟双删策略
就是先删缓存,再更新数据库,然后等线程 sleep 一会再删一遍缓存先更新数据库,后删除缓存
这个会存在并发问题吗?会,但是概率太低,几乎不可能

在这种情况下,才会出现读取到老数据的情况
但是一般情况下,写操作的请求时间往往会比读操作长,在 3-6 的间隙里做不完这么多事情
为什么要删除缓存而不是更新缓存?
更新缓存会涉及到很多无用操作,很多时候
Redis
中存储的数据和MySQL
中并不是一一对应的,而是通过处理后才写入到Redis
中缓存更新后并不会立马被访问到,这时
Redis
中就会存放这一份冗余的数据,会造成一定的浪费
先更新数据库,再删除缓存,一个操作成功,一个操作失败怎么办?
这是由于系统故障导致的一致性问题
解决方案
可以使用消息队列,更新数据库成功后往消息队列发消息,消费到消息后再删除缓存
订阅数据库变更日志
binlog
(消息队列的进阶版,不用侵入到业务代码,比如canal
)
两种方案的本质都是重试