《从零开始带你成为消息中间件实战高手》 笔记六

本文详细探讨了RocketMQ在订单库数据同步过程中出现的消息乱序问题,提出了解决方案,包括确保订单binlog进入同一MessageQueue,使用单线程消费者保证顺序消费,以及利用延迟消息机制优化定时任务。同时分享了RocketMQ实践中的经验,如利用tags过滤数据,基于消息key定位丢失消息,以及提高消费者吞吐量的方法。在面对大规模消息积压时,提出了快速消耗积压消息的策略。最后,对于金融级系统的高可用方案,强调了在MQ集群崩溃后的消息顺序恢复重要性。

一、第七十八课  为什么基于RocketMQ进行订单库数据同步时消息会乱序

场景:通过canal同步mysql数据,并把binlog消息放入RocketMQ,同步系统从MQ中同步消息写入别的库,实现数据同步

问题:数据同步后,发现两边的数据不一致

发生原因:比如有2条SQL,应该先insert,再update,结果同步时先update了,再insert,导致数据不一致

底层原因:因为一个Topic可以指定多个MessageQueue,写入消息时,消息也会均匀分配给多个MessageQueue。所以可能insert写入了MessageQueue1,update写入了MessageQueue2。接着消费端使用了多台机器组成了Consumer Group,所以可能一台机器负责消费MessageQueue1,一台机器负责消费MessageQueue2。导致消息的乱序消费

二、第七十九课  如何解决RocketMQ订单库数据同步的消息乱序问题

1、让订单的binlog都进入同一个MessageQueue

2、一个Consumer可以处理多个MessageQueue,但一个MessageQueue只能有一个Consumer处理,所以同步只能交给一台消费者机器处理

3、消息处理失败不能走重试队列,因为返回ConsumeConcurrentlyStatus.RECONSUME_LATER会跳过当前消息,处理下一条,导致消费乱序。必须返回ConsumeConcurrentlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENT,意思是先等一会,一会儿再处理这批消息,而不是把消息放到重试队列里

三、第八十课  第七十九课的代码落地

1、让订单的binlog都进入同一个MessageQueue

除message外,要传入MessageQueueSelector,在匿名内部类中指定进入哪个MessageQueue

2、消费者如何保证按照顺序获取一个MesageQueue中的消息

使用MessageListenerOrderly,会让Consumer对每一个MessageQueue,只使用一个线程处理

四、第八十一课  使用RocketMQ的过滤机制,提高同步效率

在发送时给消息设置tag、属性,在消费时过滤指定tag、属性的消息

五、第八十二课  基于延迟消息机制优化大量订单的定时退款扫描问题

场景:用户在下订单后,不一定会支付,那么30分钟后,要把未支付的订单自动取消掉

问题:如何在30分钟后,将未支付的订单取消掉?最简单的方法,就是不停查询数据库中未支付且已经超过30分钟的订单。但这样首先性能不太好,需要不停的查询,并且在分布式环境下,订单数据可能存在不同的数据库服务器上,所以不太好查询

方案:使用RocketMQ中的延迟消息,在创建订单后,设置30分钟后才能被订单扫描服务消费到,然后服务就去查询该订单是否支付成功了,没有支付成功就关闭。这样一个订单只会查询一次,并且可以组成Consumer Group减小压力

六、第八十四课  在RocketMQ的生产实践中积累的经验总结

1、灵活运用tags来过滤数据

2、基于消息key来定位消息是否丢失

要根据规则给消息设置key,这样一旦消息丢失了,我们可以去RocketMQ根据key查询该消息,进行排查

3、消息零丢失方案的补充

对之前的消息零丢失方案的补充,如果MQ集群全部挂了,那怎么办?生产者就要把消息写入本地文件或数据库暂存起来

4、提高消费者的吞吐量

  • 增加Consumer Group的机器数量,对应的MessageQueue数量也要增加
  • 增加Consumer单台机器的线程数量
  • 开启消费者的批量消费功能,这样回调函数中就可以一次处理多条消息了

5、要不要消费历史消息

consumer支持设置从哪里开始消费

七、第八十六课  如何对RocketMQ集群进行消息轨迹的追踪

1、如何知道这个消息是哪个Producer发出来的,进入了哪个Topic,又是被哪个Consumer消费的

  • 在broker的配置文件中设置traceTopicEnable=true
  • 在创建Producer准备发送消息时,设置enableMsgTrace=true
  • 在创建Consumer订阅消息时,也设置第二个属性为true

这样,在RocketMQ控制台的消息轨迹页面中,就可以根据messageId,messageKey,topic进行查询

八、第八十七课  由于消费系统故障,导致MQ有百万消息积压,该怎么办

  • 如果消息不重要,可以丢失,那么修改消费者代码,将积压的消息都不做任何处理直接消费掉。然后再改回来,正常处理实时消息
  • 如果MessageQueue数量明显大于消费者机器数,那么就临时增加机器给消费者,提高消费速度,尽快将积压的消息处理完,但要注意数据库等能否抗住
  • 如果MessageQueue数量跟消费者机器数差不多,那么增加机器给消费者也没有用。可以修改消费者代码,将积压的消息写入新的Topic,Topic的MessageQueue多弄些,再增加机器给消费者消费这个新的Topic。最后再改回来

九、第八十八课  金融级系统如何针对RocketMQ集群崩溃设计高可用方案

第84课提到一点,MQ集群崩溃后,生产者要将消息写入本地硬盘或数据库中,待MQ集群恢复后,要再把这些消息重新发到MQ中。要特别注意,写入和重新发送都要按照原来的顺序

思考题:

1、一个Producer,往一个Topic发数据,Topic内有多个MessageQueue,一个Consumer订阅这个Topic,会有消费乱序问题吗?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值