记一次事务里发普通消息的线上问题排查过程

程序员蜗牛g 2024年08月29日 12:02 江苏

1 结论

结论先行:事务+MQ的使用场景,使用方式一定得正确,稍有不慎,可能就会带来数据不一致问题。

2 问题背景及现象

图片

图片

3 排查过程

3.1 初次分析

图片

图片

发现问题,及时修复,加完锁上线,以为问题修复了,结果高兴太早了。

图片

3.2 问题再次出现

图片

图片

3.2.1 分析思路一

图片

3.2.2 分析思路二

图片

图片

图片

3.2.3 分析思路三

图片

图片

图片

b.updateCostSuccess接口里,其实包含了三步操作,执行完后,还处于大事务中,事务并未提交,后面还有处理流程。

图片

图片

c.具体过程如下

图片

3.3 解决方案

找到问题,测试环境验证一下猜想,updateCostSuccess后,延迟事务提交,基本可以稳定复现问题。

图片

解决方案就清晰了,发送MQ移步到事务提交成功后即可,修复上线后,继续观察了一段时间预警,没有再次出现该问题了,到此,该问题得到彻底解决。

图片

完整流程如下:

图片

4 总结与反思

对于有经验的工程师来说,可能一眼就知道了问题在哪里,比如我们架构的同事们,但是对于没经验,或者没有考虑到这个点上的工程师来说,可能就比较难发现原因,属于典型但不复杂的场景。

大家可以想一想,这个问题中,哪些环节有问题,可能带来当前的数据不一致结果。
数据不一致,有两个大方向的原因:

  • a.数据冗余导致;

  • b. 并发控制不好导致。

这个问题,这两个都有一定的关联,对于cost字段,系统A里已经有一份原始数据,是否有必要在系统B的业务订单表biz_business_order中再存一份,值得思考。对于并发控制,系统B消费系统Atopic,不同tag=create || update的MQ时,如果不做并发锁控制,也可能导致系统B中cost字段产生不一致。
基于本次出现的这个case,我们内部也进行了讨论学习,对于数据一致性问题,总结了几条建议,分享给大家。

  1. 数据是否冗余值得思考,如果选择冗余来降低系统复杂性,就需要用程序保证数据一致性。

  2. 涉及到数据一致性的场景,对于重要的业务场景,最好有数据校对和预警,便于提前发现问题。

  3. 对于业务较复杂的场景,大事务+MQ结合的使用,代码一定要多review,否则可能存在隐患,要谨慎。

  4. 如果事务中发MQ,就需要用事务MQ,保证逻辑处理的结果和发送MQ的结果一致,否则就可能产生不一致(业务不一致或数据不一致)。比如这个场景中,系统A update后发出的MQ,发送成功,如果后续事务回滚了,消费方系统B就可能产生业务不一致问题。

  5. 对于大事务操作,比如用注解直接包住一个大方法这种方式,要慎用。

最后说一句(求关注!别白嫖!)

如果这篇文章对您有所帮助,或者有所启发的话,求一键三连:点赞、转发、在看。

关注公众号:woniuxgg,在公众号中回复:笔记  就可以获得蜗牛为你精心准备的java实战语雀笔记,回复面试、开发手册、有超赞的粉丝福利!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值