rocketmq怎么保证队列完全顺序消费?

实际上,RocketMQ是支持顺序消费的。 但这个顺序,不是全局顺序,只是分区顺序。要全局顺序只能一个分区。 之所以出现你这个场景看起来不是顺序的,是因为发送消息的时候,消息发送默认是会采用轮询的方式发送到不通的queue(分区)。如图: 而消费端消费的时候,是会分配到多个queue的,多个queue是同时拉取提交消费。 如图: 但是同一条queue里面,RocketMQ的确是能保证FIFO的。那么要做到顺序消息,应该怎么实现呢——把消息确保投递到同一条queue。 rocketmq消息生产端示例代码如下: 按照这个示例,把订单号取了做了一个取模运算再丢到selector中,selector保证同一个模的都会投递到同一条queue。 即: 相同订单号的--->有相同的模--->有相同的queue。 最后就会类似这样: 这样同一批你需要做到顺序消费的肯定会投递到同一个queue,同一个queue肯定会投递到同一个消费实例,同一个消费实例肯定是顺序拉取并顺序提交线程池的,只要保证消费端顺序消费,则大功告成! 如何保证顺序消费? 如果是使用MessageListenerOrderly则自带此实现,如果是使用MessageListenerConcurrently,则需要把线程池改为单线程模式。 (这里假设触发了重排导致queue分配给了别人也没关系,由于queue的消息永远是FIFO,最多只是已经消费的消息重复而已,queue内顺序还是能保证) 但的确会有一些异常场景会导致乱序。如master宕机,导致写入队列的数量上出现变化。 如果还是沿用取模的seletor,就会一批订单号的消息前面散列到q0,后面的可能散到q1,这样就不能保证顺序了。除非选择牺牲failover特性,如master挂了无法发通接下来那批消息。 从消费端,如果想保证这批消息是M1消费完成再消费M2的话,可以使用MessageListenerOrderly接口,但是这样的话会有以下问题: 1. 遇到消息失败的消息,无法跳过,当前队列消费暂停 2. 目前版本的RocketMQ的MessageListenerOrderly是不能从slave消费消息的。 更多分析请参考: RocketMQ--角色与术语详解 - 薛定谔的风口猪 RocketMQ--水平扩展及负载均衡详解 - 薛定谔的风口猪

 

 

https://www.zhihu.com/question/30195969

猜你喜欢

转载自m635674608.iteye.com/blog/2395826