
大家好,我是君哥。今天聊一聊 RocketMQ 的顺序消息实现机制。
在有些场景下,使用 MQ 需要保证消息的顺序性,比如在电商系统中,用户提交订单、支付订单、订单出库这 3 个消息应该保证顺序性,如下图:

对于 RocketMQ 来说,主要是通过 Producer 和 Consumer 来保证 消 息顺序的。
1、Producer
下面代码是 Producer 发送顺序消息的官方示例:
public static void main(String[] args) throws UnsupportedEncodingException {
try {
DefaultMQProducer producer = new DefaultMQProducer("please_rename_unique_group_name");
producer.start();
String[] tags = new String[] {"TagA", "TagB", "TagC", "TagD", "TagE"};
for (int i = 0; i < 100; i++) {
int orderId = i % 10;
Message msg =
new Message("TopicTestjjj", tags[i % tags.length], "KEY" + i,
("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET));
SendResult sendResult = producer.send(msg, new MessageQueueSelector() {
@Override
public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
Integer id = (Integer) arg;
int index = id % mqs.size();
return mqs.get(index);
}
}, orderId);
System.out.printf("%s%n", sendResult);
}
producer.shutdown();
} catch (MQClientException | RemotingException | MQBrokerException | InterruptedException e) {
e.printStackTrace();
}
}
跟发送并发消息不一样的是,发送消息时传入了 MessageQueueSelector,这里可以指定消息发送到固定的 MessageQueue。
注意:上面的代码把 orderId 相同的消息都会发送到同一个 MessageQueue,这样同一个 orderId 的消息是有序的,这也叫做局部有序。对应的另一种是全局有序,这需要把所有的消息都发到同一个 MessageQueue。
下面再来看一下发送的代码:
private SendResult sendSelectImpl(
Message msg,
MessageQueueSelector selector,
Object arg,
final CommunicationMode communicationMode,
final SendCallback sendCallback, final long timeout
) throws MQClientException, RemotingException, MQBrokerException, InterruptedException {
//省略部分逻辑
TopicPublishInfo topicPublishInfo = this.tryToFindTopicPublishInfo(msg.g

本文通过五部分详细讲解 RocketMQ 顺序消息的实现,包括 Producer 的发送策略、Consumer 的消费处理、重试机制及总结。核心是通过 Producer 的 MessageQueueSelector 确保消息发送到同一队列,Consumer 使用 MessageQueueLock 实现顺序消费,以及 Broker 端的锁管理,保证消息的顺序性。但该机制可能导致消息积压和顺序问题。
最低0.47元/天 解锁文章
1386

被折叠的 条评论
为什么被折叠?



