RocketMQ 分布式事务:订单插入DB成功,但是消息失败;如何让订单回滚

wangxi得 发布于 05/24 21:26
阅读 1K+
收藏 0

开源之夏第三届火热来袭,高校学生参与赢万元奖金!>>>

 

加载中
1
高文塞西尔

消息投递成功就不需要回滚订单,消费失败就重试加人工处理

1
星星都掉了
星星都掉了
这个是消息投递失败的业务处理问题,一般有这几种处理方式:
第一种利用重试机制,导致消息例如每两秒重新投递一次,因为有可能因为网络波动原因,某一次失败,后面消息投递以及消息会恢复正常。选择重试机制的话,可以监听消息消费后的返回值,正常消费会返回 CONSUME_SUCCESS。
 
第二种回滚数据库事务。配置数据库回滚。首先也是拿到消息消费的结果,如果消费失败,抛出异常,触发事务回滚操作。这里建议不要配置自动回滚(阿里开发规范已经明确禁止),而是在catch 异常后,调用手动回滚的方法执行。
 
还可以结合定时任务去处理,将发送出去的消息存储到一张表里面,通过定时任务扫描数据的失败状态,来处理自己的业务(回滚或者是重试)。之前看过一篇关于消息处理如何保持最终一致性的文章就是用的这种方式,也是基于分布式事务。
 
配置事务回滚还要看个人项目架构,如果跟service跟调用mapper的接口是同一个服务,在本服务配置回滚就可以;如果是通过feign远程调用,那就需要开启全局服务配置,在更新的过程中,某个服务出现下线或假死的情况,会导致本次更新数据不一致,从而达不到业务处理需求。
楼主的第二张图看着怪怪的,代码191行,sql执行结果只有大于0和等于0这两种情况吧,我理解的是插入失败,则回滚事务。
 
注:消息的广播模式, 是不存在消息重试的机制的,即消息消费失败后,不会再重新进行发送,而只是继续消费新的消息。而对于普通的消息,当消费者消费消息失败后,你可以在消息监听器接口的实现中设置返回状态达到消息重试的结果。
可以有三种设置方式:
消费成功:返回CONSUME_SUCCESS,
消费失败:
方式1:返回RECONSUME_LATER,消息将重试
方式2:返回null,消息将重试
方式3:直接抛出异常, 消息将重试

1
maradona
maradona

事务消息可管不到你消费消息出现bug失败的场景的,这只能人工处理了.

他解决的问题是,发送方事务和消息的一致性,消费者出问题,那你得解决消费者的代码问题.

1
Kit_lee
Kit_lee

无论是JMS还是AMQP都有消息方确认消息消费的应答方式(ack和nack),默认的实现是autoAck的,就是消息到你侦听器的onMessage方法就已经给消息服务发送ack应答了。这样你在本地消费消息时再出异常,这个消息就死了。

如果你一定要希望消息返回到queue上边让其他消费端继续消费,可以改配置取消autoAck,我记得应该是在connectionFactory中有setAutoAck(boolean)的方法。但这个也不推荐。

原因是:如果这个消息就是有问题的导致你插入不了数据库,那你重新将消息放回queue上边,其他 消费端处理也是有问题。最终还可能导致所有消费端不能工作的恶果。

我建议可以将失败的消息放到数据库,然后记录重试次数,再用一个计划任务重新处理。

如果是想通知其他服务做一些事务回滚,也可以专门发一个回滚gkt消息到其他服务实现回滚

OSCHINA
登录后可查看更多优质内容
返回顶部
顶部
返回顶部
顶部