业务中经常有这种需求,比如新增一个订单,需要发 mq 消息到下游系统。看到把这两个操作放到一个事务的写法,那么这么做能达到这么写的目的吗(写数据 /发消息符合事务的四个特性)?
个人总觉得这么写是有问题的,但是说不出根本的问题点是什么。大家这种需求一般是怎么实现的?
1
13823133214 2020-10-19 11:20:42 +08:00
确保生产者发送成功
|
2
zczy 2020-10-19 11:22:35 +08:00
两套系统单纯加个事务还是有问题的吧,万一 mq 成功了,网络有问题回滚了数据库
|
3
coyove 2020-10-19 11:26:13 +08:00
你的担心其实来自于数据库 tx commit 失败的情况,如果不是分布式事务的话这种概率太小了,靠对账和 ack 就可以
|
4
zpfhbyx 2020-10-19 11:27:22 +08:00
mq 不要混到事务里, 生产者失败的话重试或者落 db,事务回滚不依赖 mq...
|
5
hun2008hun 2020-10-19 11:27:28 +08:00
发消息是网络请求,结果是(成功、失败、超时),超时的时候本地事务要 commit 还是 rollback 呢?
|
6
zczy 2020-10-19 11:31:07 +08:00
幂等 + ack 基本上能保证了吧
还有什么本地消息表之类的,用数据库事务保证 |
7
rihkddd OP |
9
GGGG430 2020-10-19 12:48:13 +08:00
你说的事务是本地事务表吗, 如果是那就是分布式事务的操作, 用本地事务表来保证发送消息成功.
是不是还有一个定时任务监视本地事务表呢, 正常流程是发送消息成功后删除本地事务表中关联的数据行, 没法送成功则会有后续的定时任务来重发 |
10
jorneyr 2020-10-19 13:24:37 +08:00 1
1. 落库,标记为待处理
2. MQ 发送成功 3. MQ 的回调处理落库的数据,标记为处理完成 |
11
sambawy 2020-10-19 13:51:31 +08:00
不要混在一起,消息发送的成功与否不要影响数据状态的落库,否则会因为一两个消息发送的异常导致一批数据回滚,到时候客户那边就被消息轰炸了
|
12
CoderGeek 2020-10-19 14:06:32 +08:00 1
常用手段是本地事务消息, 一般是集中业务库中会有个 localmessage 随着业务比如订单的落库一起保存这 message,然后使用 TransactionSynchronizationAdapter 巴拉巴拉的啥的 保证消息与业务 DB 操作在一个事务,然后应用的线程异步发送 mq 或者半同步这一类的
问题是性能受影响,下游需要幂等 多余的服务开销 但是做肯定是做的到的 |
13
CoderGeek 2020-10-19 14:08:56 +08:00
常用的应该是我说的第一类
```java begin transaction biz_code(); insertMessage(); callback(); end; callback 方案可以使用 spring 事务机制进行回调 function callback(){//异步 or 同步 var rtn = sendMqMessage(); If(rtn){ delMessage(); } } 对于 callback 发送失败问题,会有定时任务去消息表里面获取未成功发送的消息进行重试,在一定次数还为成功的消息,报警人工干预。 ``` |
14
nutting 2020-10-19 15:07:59 +08:00
发消息可能比较耗时吧,不能放到事务里,我觉得是这个角度考虑?
|
16
zhangdashuan 2020-10-20 09:21:53 +08:00
用事务消息应该可以避过这个问题
|
17
RedBeanIce 2020-10-20 09:33:38 +08:00
看到支付的流程图
写库,发送消息,调用支付,要放到一个事务里面。 否则你写了库也是脏数据,没有人回去消费他 |