< 3; i++) {Message msg = new Message("TopicTest", tags[i], ("Hello RocketMQ " + i).getBytes(StandardCharsets.UTF_8));// 在消息发送时传递给事务监听器的参数SendResult sendResult = producer.sendMessageInTransaction(msg, null);System.out.printf("%s%n", sendResult);}// 关闭生产者producer.shutdown();}}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
文章插图
图片
其核心部分就是 TransactionListener 实现 , 其他部分与正常的消息发送基本一致,TransactionListener 主要完成:
- 执行本地事务,也就是业务操作;
- 执行结果检测,通过反查业务数据,决定消息的后续处理策略;
事务消息存在一定的问题:
- 与 MQ 实现强相关,并不是每个 MQ 实现都对事务消息提供支持;
- API 比较晦涩,存在一定的学习成本,同时需要对业务逻辑拆分到 Listener 中,增加理解成本;
3.3.2.2. 事务消息表事务消息表方案是一种常用的保证消息发送与业务操作一致性的方法 。该方案基于数据库事务和消息队列,将消息发送和业务操作放入同一个事务中 , 并将业务操作和消息发送的状态记录在数据库的消息表中,以实现消息的可靠性和幂等性 。
如下图所示:
文章插图
图片
核心流程如下:
- 应用程序开启一个数据库事务,并在事务中执行业务操作和消息发送;
- 在事务中,将业务操作和消息发送的状态记录到消息表中;
- 如果业务操作执行成功 , 并且消息发送成功,提交事务,否则回滚事务;
- 定时扫描消息表 , 并根据消息状态重新发送未被确认的消息 。如果消息发送成功,更新消息状态;否则根据重试次数更新消息状态或者丢弃消息;
作为一种通用解决方案,lego 对其进行支持 , 可参考 reliable-message 模块 。
4. 业务补偿不管在设计时使用哪种方案,都是在尽力降低不一致出现的概率,但可怕的是不一致问题终究会发生 。
是不是有些奇怪,做了这么多还是无法从根源上彻底解决一致性问题,在实际工作中就是这样:
- 并不是所有的可补偿事务都能回滚成功:在正向流程中我们都会对资源进行锁定 , 如果其他操作破坏了锁定资源或者破坏了准入条件,程序将无法正常回滚,必须人工介入进行解决 。比如,生单时成功锁定优惠券,但超管发现优惠券发放错误对其进行回收 , 在进行优惠券回滚时,由于优惠券处于不可用状态,导致无法正常回滚;
- 并不是所有的可重试事务都能重试成功:业务执行到可重试事务,只能证明其满足关键事务之前的条件,并不一定满足下游可重试事务的条件 。比如,支付成功后需要给用户发送微信消息 , 但用户授权信息已经过期导致消息无法发送;
推荐阅读
- 当44岁的胡杏儿和张雨绮娜然同框,才彻底明白,港女的保养真绝
- 疯马秀“审判”后续:张嘉倪,杨颖或遭软封杀,Lisa彻底凉凉!
- 首位90后女主播登《新闻联播》,看完她的履历后,我彻底服了!
- 谢贤公开与张柏芝关系,遮羞布彻底被揭,谢霆锋得知后连忙澄清
- 安卓怎么彻底删除微信聊天记录 怎么彻底删除微信聊天记录
- 终于处罚了!Lisa被封号,杨颖张嘉倪被禁言,星光之路彻底是凉凉了
- 一个“假向太”,彻底揭开了向家的豪门真相,难怪郭碧婷会退圈!
- Lisa风波迎来大结局,3女星彻底沦为弃子,LV3公子成唯一聪明人
- 家里有老鼠怎么能彻底消灭 老鼠对粘鼠板有记忆吗
- baby彻底凉凉?被曝向黄晓明求救,准备跑路出国抛售5亿豪宅?