RocketMQ如何保证消息的顺序性?

在一些证券和购票的场景中,按照交易逻辑,谁先出价谁先交易的原则,针对相同的报价单,使用MQ处理订单时,就需要严格按照出价顺序处理订单,也就要保证消息的顺序性。

RocketMQ本身是支持顺序消息的,但其实也是有一定限制的:

官方文档中提到,顺序消息的是利用队列先进先出的特性,通过消息组实现的,也就是说只有在相同消息组中,才能够实现消息的顺序性

生产顺序性

RocketMQ通过生产者和服务端协议保障每个生产者串行发送消息,并按顺序存储和持久化,如需保证消息生产的顺序性,则必须满足以下条件:

  • 单一生产者:消息生产的顺序性仅支持单一生产者,不同的生产者分布在不同的系统,即使设置相同的消息组,不同生产者之间产生的消息也无法判断其生产的先后顺序。

  • 串行发送:如果生产者使用多线程并行发送,不同线程之间的消息顺序是没有办法保证先后的。因此,需要保证消息被串行发送。

消费顺序性

在保证生产顺序性后,消息在消息组中就是顺序存储的了,此时我们只需要将消息顺序取出消费就可以了,这里需要注意的是:

  • 串行消费:如果是并行消费,可能会因为网络延迟导致后取出的消息比先取出的消息先消费完,同样无法保证消息的顺序性,而串行消费能够确保只有当前一个消息被消费完,才会去消费下一个消息。

  • 有限重试:RocketMQ顺序消息的投递失败的重试是有次数限制的,当超过最大重试次数后,会跳过这条消息,不阻塞后续消息的处理,因此需要设置合理的重试次数,避免参数不合理导致消费乱序。

总结

  1. RocketMQ中,单个消费组中的消息是有序的,因此,实现消息顺序的前提是要将消息顺序投递到同一个消费组中。比如,自定义一个路由算法,确保同一个商品的订单能被路由到同一个消息组中。

  2. 单一生产者串行发送消息,确保消息被顺序发送。同一个商品的订单消息由同一个生产者发送。

  3. 消费者串行消费,避免并行消费导致消息被乱序消费。

  4. 合理设置重试次数,避免跳过部分消息导致消费乱序。

### RocketMQ 中实现消息顺序消费的方法 #### 机制解析 RocketMQ 提供了两种主要的方式用于保障消息顺序消费,即分区顺序消息(Partition Ordered Messages)和全局顺序消息(Global Ordered Messages),两者均能确保消息按照发送时的先后次序被消费者处理[^3]。 对于 **分区顺序消息** 而言,在同一主题下的不同队列之间可以并行消费;然而针对单个队列内的消息,则采用串行化的方式来保证该队列内消息的严格有序。这种方式既提高了系统的吞吐量又满足了一定程度上的业务需求——当只需要部分数据保持相对顺序即可的情况下尤为适用。 至于 **全局顺序消息**, 则更为严格地控制着整个Topic下所有Message都必须依照生产者写入Broker的时间戳来进行逐一读取操作, 这种模式适用于那些对整体流程有着极高同步度要求的应用场景之中. 由于为了实现顺序消费引入了三把锁,这确实会在一定程度上降低并发能。因此破局思路在于重新审视这些锁定策略以及探索其他可能的技术手段来缓解这一矛盾,比如通过调整业务逻辑减少对绝对顺序的依赖或是优化内部算法提高效率等措施[^1]。 #### 配置方法 要启用RocketMQ中的顺序消费特,开发者可以在创建`DefaultMQPushConsumer`实例之后设置相应的监听器类: ```java consumer.subscribe("YourTopicName", "*", new MessageListenerOrderly() { AtomicLong consumeTimes = new AtomicLong(0); @Override public ConsumeOrderlyStatus consumeMessage(List<MessageExt> msgs, ConsumeOrderlyContext context) { try { // Process messages here. return ConsumeOrderlyStatus.SUCCESS; } catch (Exception e) { return ConsumeOrderlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENT; } } }); ``` 上述代码片段展示了如何注册一个实现了 `MessageListenerOrderly` 接口的对象作为回调函数,每当有新一批待处理的消息到达时就会触发此接口里的 `consumeMessage()` 方法执行具体的业务逻辑[^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值