A.先写 DB,再更新 cache。在更新 cache 时失败,则不一致。
B.先更新 cache,再写 DB。在更新 cache 后,写 DB 完成前,有新的查询过来,则旧的DB值,会覆盖新的 cache。如果更新 cache 成果,写 DB 失败,也会导致不一致。
C.先更新 cache,再写 DB,再更新 cache。则 AB 俩种情况都有可能出现。
区分需求场景
A.要求强一致性的场景下:
方案一:可通过分布式锁,将并行更新的场景先串行化,避免并发导致的数据覆盖。
1 这样可以先删除 cache,
2 更新DB,
3 再更新一下cache。
这样即使更新cache 失败,下一次查询也会补充上。
方案二:定时任务方式.
搞一个 job,定时去扫DB中的数据,然后更新redis 缓存。
允许一定时间的不一致,保证最终一致性即可的场景下:
方案一 基于消息队列解决:
1 先更新DB,
2 再将结果投递到rocketMq 中,由MQ的消费者去更新cache。
注: 这里只需要保证MQ不丢消息,通过ack机制,可以保证最终一致性。这里对DB是主从同步的架构下,如果发生同步延迟,写主读从时,可能会导致不一致。不过,这个概率相对更低。担心的话,可以写主读主。
方案二 基于MySql 的binlog+MQ 去解决。(可以相对较好的解决方案一中DB主从同步延迟的问题)
1 先更新DB,
2 再通过Canal中间件读取binlog日志,
3 Canal借助于限流组件按频率将数据发到MQ中。
4 应用监控MQ通道,将MQ的数据更新到Redis缓存中。
注: 参考文章:
https://www.w3cschool.cn/architectroad/architectroad-consistency-of-cache-with-master-and-slave-database.html
https://www.w3cschool.cn/architectroad/architectroad-cache-architecture-design.html
https://coolshell.cn/articles/17416.html
还有一些其他文章,现在找不到啦。
欢迎拍砖,可 tangyuandx 相互交流学习~




