A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 庭院深深深几许 金牌黑马   /  2019-4-18 10:49  /  1012 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

  实际上,RocketMQ是支持顺序消费的。
  但这个顺序,不是全局顺序,只是分区顺序。要全局顺序只能一个分区。
  之所以出现你这个场景看起来不是顺序的,是因为发送消息的时候,消息发送默认是会采用轮询的方式发送到不通的queue(分区)。如图:

v2-612e7eaad6734189fdb6c927a9a1d520_hd.jpg

  而消费端消费的时候,是会分配到多个queue的,多个queue是同时拉取提交消费。
  如图:

v2-7996e367c2036282ff5f757c492453ae_hd.jpg

  但是同一条queue里面,RocketMQ的确是能保证FIFO的。那么要做到顺序消息,应该怎么实现呢——把消息确保投递到同一条queue。
  rocketmq消息生产端示例代码如下:

v2-27f36015d665e3a527fabb795f0ccee2_hd.jpg

  按照这个示例,把订单号取了做了一个取模运算再丢到selector中,selector保证同一个模的都会投递到同一条queue。
  即: 相同订单号的--->有相同的模--->有相同的queue。
  最后就会类似这样:

v2-e6095992cd28d5d3896825f9c4f562ca_hd.jpg

  这样同一批你需要做到顺序消费的肯定会投递到同一个queue,同一个queue肯定会投递到同一个消费实例,同一个消费实例肯定是顺序拉取并顺序提交线程池的,只要保证消费端顺序消费,则大功告成!
  如何保证顺序消费? 如果是使用MessageListenerOrderly则自带此实现,如果是使用MessageListenerConcurrently,则需要把线程池改为单线程模式。
  (这里假设触发了重排导致queue分配给了别人也没关系,由于queue的消息永远是FIFO,最多只是已经消费的消息重复而已,queue内顺序还是能保证)
  但的确会有一些异常场景会导致乱序。如master宕机,导致写入队列的数量上出现变化。
  如果还是沿用取模的seletor,就会一批订单号的消息前面散列到q0,后面的可能散到q1,这样就不能保证顺序了。除非选择牺牲failover特性,如master挂了无法发通接下来那批消息。
  从消费端,如果想保证这批消息是M1消费完成再消费M2的话,可以使用MessageListenerOrderly接口,但是这样的话会有以下问题:
  1. 遇到消息失败的消息,无法跳过,当前队列消费暂停 2. 目前版本的RocketMQ的MessageListenerOrderly是不能从slave消费消息的。

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马