Redis 中如何保证缓存与数据库的数据一致性

可以分为先操作缓存和先操作数据库两种方式,更新缓存中的数据都是采用删除的方式,等到下一次查询时从更新之后的数据库中再写入缓存。

如果说先删除缓存,那么会出现下面这种情况,当线程 1 删除缓存之后,由于网络延迟,线程 2 先执行查询操作,没有查询到目标数据之后,就会从数据库中把旧的数据写入缓存中,然后线程 1 再更新数据库,此时虽然数据库中是更新之后的数据,但是之后再进行查询的时候,由于缓存中已经又重新被写入了旧数据,此时就会出现数据不一致的问题

解决方案是通过延迟双删的方式,第一次线程 1 删除缓存,等到数据库中的数据更新之后,延迟一段时间再进行删除缓存,通过两次删除,就能保证之后再获取缓存中的数据时不会获取到脏数据,而延迟一段时间再删除是为了确保线程 2 把旧数据写入缓存之后再进行删除,不然即使执行双删操作,旧数据也会重新被写入缓存,双删了个寂寞。

再来看先操作数据库的方案:

先把数据写入到数据库,然后再删除缓存,这种方式其实还是存在问题,如果删除缓存时删除失败了,那么之后查询到的还是旧数据,还是存在数据不一致问题。

针对缓存删除失败的情况,可以采用删除重试的方式,重试的操作可以添加到 MQ 中,通过异步的方式来处理,这样的话代码的耦合度也会上来,如果要实现解耦,可以采用读取 binlog 来进行异步删除。

最终的方案就是:先修改数据库,然后通过 Canal 监听数据库的 binlog 日志,记录数据库的修改信息,然后通过消息队列异步修改缓存的数据,需要注意保证缓存中数据按顺序更新,然后加上重试机制,避免由于网络问题导致更新失败

相关推荐
AI小百科3 小时前
向量数据库:AI 的「记忆仓库」是怎么工作的
数据库·人工智能·oracle
煎饼皮皮侠3 小时前
【设计】设计一个Web版数据库管理平台(之七):多数据库类型易扩展
数据库
Nturmoils3 小时前
MongoDB迁移之后,Spring Data 和 Hibernate 各自接哪类请求
数据库
画中有画4 小时前
在自动化脚本中操作本地数据库
数据库·oracle·自动化
Decay__4 小时前
09_MySQL 闪回与时间点恢复 —— binlog 回放、mysqlbinlog、PITR 与误删恢复
运维·数据库·sql·mysql·架构
太理摆烂哥4 小时前
MySQL用户管理
数据库·mysql
梦影_6 小时前
MySQL进阶教程(五)—— SQL调优(下)
android·大数据·数据库·后端·sql·mysql·database
考虑考虑6 小时前
mariadb数据库
数据库·后端·mariadb
John_Hui8 小时前
Windows 10 安装版本:mysql-8.1.0-winx64.zip
数据库·windows·mysql
莫晓燚8 小时前
双机部署若依 (RuoYi‑Vue) 传统环境部署---实战
linux·运维·数据库·redis·mysql·nginx·ruoyi