彦祖们,请教下这个问题有什么好的解决方案?

2021-02-25 10:52:00 +08:00
 MeloForsaken

有两个部署在不同服务器的系统 A 、B (对应的数据库也是分开的)。

正常情况:A 向 B 发请求,B 写数据库,A 根据 B 回传的信息写数据库。

现在 A 因为偶尔的网络问题没有收到 B 回传的信息,导致 B 写了数据库,A 没有写数据库,造成数据不一致。

请教下有什么方案解决这种事务问题?(网络问题不可解决的情况下)

1724 次点击
所在节点    程序员
12 条回复
xiaofan2
2021-02-25 11:03:11 +08:00
我理解你这个就相当于一个重试机制如何做幂等的问题?用订单号?每次 A 给 B 的请求都带订单号 B 写库之前查询一次是否存在
MeloForsaken
2021-02-25 11:13:41 +08:00
@xiaofan2 你的意思是 A 需要加上重试机制,保证出现网络异常的时候重复向 B 发请求,同时 B 写库前加上校验?
jmyz0455
2021-02-25 11:16:23 +08:00
单纯为标题顶一下贴🤣
Twain
2021-02-25 11:23:24 +08:00
1.业务如果是乐观性的,可以先写库,双方加一个轮询检测机制,设定时间内如果没有回执,就认为任务失败,回退下数据库
2.业务如果是悲观性的,那就要双发互发回执确认之后,才能写库了
yuchting
2021-02-25 11:28:24 +08:00
重试其实不是重要的,必须要重试。
重点是,为每一个请求、应答加一个唯一 hash,然后每次处理需要 hash 比对、存库( memcache )。
否则,在事务中等待应答,效率太低。
jjwjiang
2021-02-25 11:31:36 +08:00
你当然可以实现 B 的回滚,A 收不到反馈时让 B 进行回滚
或者 B 收到 A 的回执时再真正插入并再次发送回执让 A 真正插入

但是既然你有这样的网络问题,那以上任何解决方案都是不可靠的,因为任何策略都基于多次网络通信,你单次通信都不能保证到达,怎么保证这些多次网络通信可靠呢?

在 AB 的通信不能保证的情况下,只能再找一个双方都能访问的第三方用来做中介了,比如 MQ 或者数据库,双方都监听或者轮询这个第三方来做确认。
GGGG430
2021-02-25 11:36:47 +08:00
分布式事务解决方式,要么 tcc 三段提交,要么 mq 消息队列
yedan1206
2021-02-25 11:37:03 +08:00
使用消息队列中间件可完美解决
theOneMe
2021-02-25 11:39:09 +08:00
上 mq 吧,做解耦,最终一致就行
bitcapybara
2021-02-25 11:47:24 +08:00
分布式事务不就是用来干这个的吗?已经有很多成熟的框架了啊
markgor
2021-02-25 13:14:01 +08:00
A 发送信息给 B,B 处理完返回结果给 A,
当出现异常的时候,B 写入了但没返回给 A,
那么 A 通过异常机制启动重试机制,
只要 B 是有做幂等那就不会重复插入了。
v2orz
2021-02-25 14:35:35 +08:00
做最终一致的话,b 回传用 mq 即可
强一致的话,不考虑分布式事务的基础上,可以 B 做接口冥等,A 没有收到信息的情况下反复重试

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

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

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

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

© 2021 V2EX