编辑
2023-11-05
缓存中间件
0
请注意,本文编写于 181 天前,最后修改于 33 天前,其中某些信息可能已经过时。

1、缓存延时双删

​ 先删除缓存,再更新数据库,休眠一会(比如1秒),再次删除缓存。这个休眠时间 = 读业务逻辑数据的耗时 + 几百毫秒。为了确保读请求结束,写请求可以删除读请求可能带来的缓存脏数据。而且这个休眠时间在某些业务环境下不太好拿捏。这种方案还算可以,只有休眠那一会(比如就那1秒),可能有脏数据,一般业务也会接受的。但是如果第二次删除缓存失败呢?缓存和数据库的数据还是可能不一致。给Key设置一个自然的expire过期时间,让它自动过期怎样?那业务要接受过期时间内,数据的不一致。

2、删除缓存重试机制

延时双删可能会存在第二步的删除缓存失败,导致的数据不一致问题。可以使用这个方案优化:删除失败就多删除几次,保证删除缓存成功就可以了, 所以可以引入删除缓存重试机制。先写请求更新数据库,缓存因为某些原因,删除失败,把删除失败的key放到消息队列,消费消息队列的消息,获取要删除的key,重试删除缓存操作。

3、读取biglog异步删除缓存

​ 重试删除缓存机制还不粗,但是会造成很多业务代码入侵。其实,还可以这样优化:通过数据库的binlog来异步淘汰key。以mysql为例:可以使用阿里的canal将binlog日志采集发送到MQ队列里面,然后通过ACK机制确认处理这条更新消息,删除缓存,保证数据缓存一致性。

想要保证数据库和缓存一致性,推荐采用「先更新数据库,再删除缓存」方案,并配合「消息队列」或「订阅变更日志」的方式来做

​ 引入缓存后,需要考虑缓存和数据库一致性问题,可选的方案有:「更新数据库 + 更新缓存」、「更新数据库 + 删除缓存」。

​ 更新数据库 + 更新缓存方案,在「并发」场景下无法保证缓存和数据一致性,解决方案是加「分布锁」,但这种方案存在「缓存资源浪费」和「机器性能浪费」的情况。

​ 采用「先删除缓存,再更新数据库」方案,在「并发」场景下依旧有不一致问题,解决方案是「延迟双删」,但这个延迟时间很难评估。

​ 采用「先更新数据库,再删除缓存」方案,为了保证两步都成功执行,需配合「消息队列」或「订阅变更日志」的方案来做,本质是通过「重试」的方式保证数据最终一致。

​ 采用「先更新数据库,再删除缓存」方案,「读写分离 + 主从库延迟」也会导致缓存和数据库不一致,缓解此问题的方案是「延迟双删」,凭借经验发送「延迟消息」到队列中,延迟删除缓存,同时也要控制主从库延迟,尽可能降低不一致发生的概率。

本文作者:whitebear

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!