有两个部署在不同服务器的系统 A 、B (对应的数据库也是分开的)。
正常情况:A 向 B 发请求,B 写数据库,A 根据 B 回传的信息写数据库。
现在 A 因为偶尔的网络问题没有收到 B 回传的信息,导致 B 写了数据库,A 没有写数据库,造成数据不一致。
请教下有什么方案解决这种事务问题?(网络问题不可解决的情况下)
1
xiaofan2 2021-02-25 11:03:11 +08:00
我理解你这个就相当于一个重试机制如何做幂等的问题?用订单号?每次 A 给 B 的请求都带订单号 B 写库之前查询一次是否存在
|
2
MeloForsaken OP @xiaofan2 你的意思是 A 需要加上重试机制,保证出现网络异常的时候重复向 B 发请求,同时 B 写库前加上校验?
|
3
jmyz0455 2021-02-25 11:16:23 +08:00
单纯为标题顶一下贴🤣
|
4
Twain 2021-02-25 11:23:24 +08:00
1.业务如果是乐观性的,可以先写库,双方加一个轮询检测机制,设定时间内如果没有回执,就认为任务失败,回退下数据库
2.业务如果是悲观性的,那就要双发互发回执确认之后,才能写库了 |
5
yuchting 2021-02-25 11:28:24 +08:00
重试其实不是重要的,必须要重试。
重点是,为每一个请求、应答加一个唯一 hash,然后每次处理需要 hash 比对、存库( memcache )。 否则,在事务中等待应答,效率太低。 |
6
jjwjiang 2021-02-25 11:31:36 +08:00
你当然可以实现 B 的回滚,A 收不到反馈时让 B 进行回滚
或者 B 收到 A 的回执时再真正插入并再次发送回执让 A 真正插入 但是既然你有这样的网络问题,那以上任何解决方案都是不可靠的,因为任何策略都基于多次网络通信,你单次通信都不能保证到达,怎么保证这些多次网络通信可靠呢? 在 AB 的通信不能保证的情况下,只能再找一个双方都能访问的第三方用来做中介了,比如 MQ 或者数据库,双方都监听或者轮询这个第三方来做确认。 |
7
GGGG430 2021-02-25 11:36:47 +08:00 via iPhone
分布式事务解决方式,要么 tcc 三段提交,要么 mq 消息队列
|
8
yedan1206 2021-02-25 11:37:03 +08:00
使用消息队列中间件可完美解决
|
9
theOneMe 2021-02-25 11:39:09 +08:00
上 mq 吧,做解耦,最终一致就行
|
10
bitcapybara 2021-02-25 11:47:24 +08:00
分布式事务不就是用来干这个的吗?已经有很多成熟的框架了啊
|
11
markgor 2021-02-25 13:14:01 +08:00
A 发送信息给 B,B 处理完返回结果给 A,
当出现异常的时候,B 写入了但没返回给 A, 那么 A 通过异常机制启动重试机制, 只要 B 是有做幂等那就不会重复插入了。 |
12
v2orz 2021-02-25 14:35:35 +08:00
做最终一致的话,b 回传用 mq 即可
强一致的话,不考虑分布式事务的基础上,可以 B 做接口冥等,A 没有收到信息的情况下反复重试 |