分布式环境中,业务报错如何保证 redis 数据一致性?

2023-01-05 15:27:18 +08:00
 liyunyang
这是一个困扰我很久的问题,一直不知道有什么好的处理方式,故来此地取经。

举个例子:

分布式订单服务 A 和库存服务 B

服务 A 调用服务 B ,服务 A 修改了 redis 缓存,服务 B 报错了,全局事物回滚,服务 A 的缓存没有回滚

各位大佬,这种情况有什么推荐处理方式吗?
2109 次点击
所在节点    程序员
17 条回复
qq976739120
2023-01-05 15:30:00 +08:00
redis 的数据应该是跟着 mysql 的,所以 a 服务的数据库回滚以后,redis 应该跟着 a 服务的 mysql 走,而不是在 b 服务里做处理
liyunyang
2023-01-05 15:45:30 +08:00
@qq976739120 #1 redis 怎么回滚?
7911364440
2023-01-05 15:51:33 +08:00
加一个服务监听数据库日志,数据写入成功再刷新缓存。
leonshaw
2023-01-05 16:01:32 +08:00
@liyunyang 失效
zuixinwenyue
2023-01-05 16:06:07 +08:00
我觉得应该把修改 redis 缓存,放在调用服务 B 之后,如果调用 B 报错也不需要回滚 redis
dwlovelife
2023-01-05 16:06:28 +08:00
服务 A 为什么不等服务 B 成功了再去修改缓存
liyunyang
2023-01-05 16:16:34 +08:00
@7911364440 #3 诶,这个应该是最好的方式吧,不过实现起来比较复杂,维护成本也不低
liyunyang
2023-01-05 16:17:20 +08:00
@dwlovelife #6 一言难尽,老项目了,业务非常复杂,如果是新功能,肯定会注意到这个的
gold2022
2023-01-05 17:09:21 +08:00
@liyunyang 失效原来 redis 缓存,让他重新根据 mysql 生成缓存
CodeSorcerer
2023-01-05 18:05:20 +08:00
用 canal 来更新 redis ?
fkdog
2023-01-05 19:02:21 +08:00
将刷新缓存、发送 mq 等操作放到事务提交成功的 callback 里。
如果 A 服务在事务中修改了 redis ,那么其他线程会读到错误的缓存数据。
等事务完成同步到 db 里以后再去做缓存的更新操作。

其实有的时候也没必要追求强一致,存库实时都在变,某个用户在某个时间点看到的库存也许再下一秒就变了,只要 CUD 的时候保证一致就行了。
qq976739120
2023-01-05 21:02:54 +08:00
@liyunyang 不是回滚 redis,是 a 数据库回滚后,有个服务去修改 redis
vitoliu
2023-01-05 21:17:26 +08:00
最简单的解决方案:每次更新操作,先清空所有缓存。
notwaste
2023-01-05 21:23:41 +08:00
类似八股文很多,最常见的面试产物就是延迟双删,而且这里 A 服务不应该修改缓存而是删除缓存
Joker1995
2023-01-05 21:53:23 +08:00
我自己认为不 manual 去处理缓存,通过 canal+kafka 进行处理会好些,确实会有短时间的不一致
Haires
2023-01-06 09:03:55 +08:00
缓存应该是删除,而不是更新
pagewang
2023-01-07 07:50:33 +08:00
失败后重新生成新的缓存,只允许第一个请求去 db 查库存,其他的读缓存

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/906764

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX