五张图带你理解 RocketMQ 顺序消息实现机制

RocketMQ-如何保证顺序消息 实际开发中会有以下场景,需要保证一组消息的生产顺序与消费顺序相同,例如那么在 RocketMQ 中该如何保证消息的顺序呢? 阅读详情

大家好,我是君哥。今天聊一聊 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.getTopic());
 if (topicPublishInfo != null && topicPublishInfo.ok()) {
  MessageQueue mq = null;
  try {
   List<MessageQueue> messageQueueList =
    mQClientFactory.getMQAdminImpl().parsePublishMessageQueues(topicPublishInfo.getMessageQueueList());
   Message userMessage = MessageAccessor.cloneMessage(msg);
   String userTopic = NamespaceUtil.withoutNamespace(userMessage.getTopic(), mQClientFactory.getClientConfig().getNamespace());
   userMessage.setTopic(userTopic);

   mq = mQClientFactory.getClientConfig().queueWithNamespace(selector.select(messageQueueList, userMessage, arg));
  } catch (Throwable e) {
   throw new MQClientException("select message queue threw exception.", e);
  }
  //省略部分逻辑
  if (mq != null) {
   return this.sendKernelImpl(msg, mq, communicationMode, sendCallback, null, timeout - costTime);
  } else {
   throw new MQClientException("select message queue return null.", null);
  }
 }
    //省略部分逻辑
}

可以看到,在发送的时候,使用 MessageQueueSelector 选择一个 MessageQueue,然后发送消息到这个 MessageQueue。对于并发消息,这里不传 MessageQueueSelector,如果发送方法没有指定 MessageQueue,就会按照默认的策略选择一个。

2、Consumer

以 RocketMQ 推模式为例,消费者会注册一个监听器,进行消息的拉取和消费处理,下面的 UML 类图显示了调用关系:

上图中包含了对顺序消息和对并发消息的处理。其中 MessageListenerOrderly 和 ConsumeMessageOrderlyService 对顺序消息进行处理。跟并发消息不一样的是,顺序消息定义了一个 MessageQueueLock 类,这个类保存了每个 MessageQueue 对应的锁,代码如下:

private ConcurrentMap<MessageQueue, Object> mqLockTable = new ConcurrentHashMap<MessageQueue, Object>();

下面代码是顺序消费的官方示例:

public static void main(String[] args) throws MQClientException {
 DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("please_rename_unique_group_name_3");
 consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
 consumer.subscribe("TopicTest", "TagA || TagC || TagD");
 consumer.registerMessageListener(new MessageListenerOrderly() {
  AtomicLong consumeTimes = new AtomicLong(0);
  @Override
  public ConsumeOrderlyStatus consumeMessage(List<MessageExt> msgs, ConsumeOrderlyContext context) {
   context.setAutoCommit(true);
   System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), msgs);
   this.consumeTimes.incrementAndGet();
   if ((this.consumeTimes.get() % 2) == 0) {
    return ConsumeOrderlyStatus.SUCCESS;
   } else if ((this.consumeTimes.get() % 5) == 0) {
    context.setSuspendCurrentQueueTimeMillis(3000);
    return ConsumeOrderlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENT;
   }
   return ConsumeOrderlyStatus.SUCCESS;
  }
 });
 consumer.start();
 System.out.printf("Consumer Started.%n");
}

下面看一下顺序消息的消费端处理逻辑。

(1)注册监听

上面的代码定义了顺序消息监听器 MessageListenerOrderly,并且注册到 DefaultMQPushConsumer,这个注册同时也注册到了 DefaultMQPushConsumerImpl。

(2)PushConsumer 初始化

在 DefaultMQPushConsumerImpl 类初始化的时候,会判断注册的 MessageListener 是不是 MessageListenerOrderly,如果是,就把 consumeOrderly 变量设置为 true,以此来标记是顺序消息拉取还是并发消息拉取。然后把 ConsumeMessageService 初始化为 ConsumeMessageOrderlyService。

(3)锁定 mq

要保证消息的顺序性,就需要保证同一个 MessageQueue 只能被同一个 Consumer 消费。

ConsumeMessageOrderlyService 初始化的时候,会启动一个定时任务,周期性(默认 20s)地向 Broker 发送锁定消息(请求类型 LOCK_BATCH_MQ),Broker 收到后,就会把 MessageQueue、group 和 clientId 进行绑定,这样其他客户端就不能从这个 MessageQueue 拉取消息。

注意:Broker 的锁定是有过期时间的,默认 60s,可以配置,锁定过期后,有可能被其他 Consumer 进行消费。

Broker 端锁结构如下图:

(4)拉取消息

消费者启动时,启动消费拉取线程 PullMessageService,里面死循环不停地从 Broker 拉取消息。这里调用了 DefaultMQPushConsumerImpl 类的 pullMessage 方法。这里拉取消息的逻辑跟并发消息逻辑是一样的。

拉取到消息后,调用 PullCallback 的 onSuccess 方法处理结果,这里调用了 ConsumeMessageOrderlyService 的 submitConsumeRequest 方法,里面用线程池提交了 ConsumeRequest 线程。

PullCallback pullCallback = new PullCallback() {
 @Override
 public void onSuccess(PullResult pullResult) {
  if (pullResult != null) {
   pullResult = DefaultMQPushConsumerImpl.this.pullAPIWrapper.processPullResult(pullRequest.getMessageQueue(), pullResult,
    subscriptionData);
   switch (pullResult.getPullStatus()) {
    case FOUND:
     //省略
     if (pullResult.getMsgFoundList() == null || pullResult.getMsgFoundList().isEmpty()) {
      DefaultMQPushConsumerImpl.this.executePullRequestImmediately(pullRequest);
     } else {
      //省略
      boolean dispatchToConsume = processQueue.putMessage(pullResult.getMsgFoundList());
      DefaultMQPushConsumerImpl.this.consumeMessageService.submitConsumeRequest(
       pullResult.getMsgFoundList(),
       processQueue,
       pullRequest.getMessageQueue(),
       dispatchToConsume);
                        //省略
     }
     //省略
     break;
    //省略
   }
  }
 }
    //省略
};

上面拉取到消息后,先把消息放到了 ProcessQueue,然后调用了 submitConsumeRequest 方法。跟并发消息处理方式不同的是,submitConsumeRequest 方法并没有处理拉取到的消息,而真正处理的时候是从 ProcessQueue 获取。

(5)处理消息

处理消息的逻辑在 ConsumeMessageOrderlyService 的内部类 ConsumeRequest,这是一个线程类,run 方法如下:

public void run() {
 //省略部分逻辑
 //1.获取到 MessageQueueLock 对应的锁
 final Object objLock = messageQueueLock.fetchLockObject(this.messageQueue);
 synchronized (objLock) {
  if (MessageModel.BROADCASTING.equals(ConsumeMessageOrderlyService.this.defaultMQPushConsumerImpl.messageModel())
   || (this.processQueue.isLocked() && !this.processQueue.isLockExpired())) {
   final long beginTime = System.currentTimeMillis();
   for (boolean continueConsume = true; continueConsume; ) {
    //省略延后执行的逻辑
    final int consumeBatchSize =
     ConsumeMessageOrderlyService.this.defaultMQPushConsumer.getConsumeMessageBatchMaxSize();
                //2.从 processQueue 拉取消息
    List<MessageExt> msgs = this.processQueue.takeMessages(consumeBatchSize);
    if (!msgs.isEmpty()) {
     final ConsumeOrderlyContext context = new ConsumeOrderlyContext(this.messageQueue);

     ConsumeOrderlyStatus status = null;
                    //省略部分逻辑
     boolean hasException = false;
     try {
         //3.获取处理锁
      this.processQueue.getConsumeLock().lock();
      //4.执行消费处理逻辑
      status = messageListener.consumeMessage(Collections.unmodifiableList(msgs), context);
     } catch (Throwable e) {
      log.warn(String.format("consumeMessage exception: %s Group: %s Msgs: %s MQ: %s",
       RemotingHelper.exceptionSimpleDesc(e),
       ConsumeMessageOrderlyService.this.consumerGroup,
       msgs,
       messageQueue), e);
      hasException = true;
     } finally {
         //5.释放处理锁
      this.processQueue.getConsumeLock().unlock();
     }
     //省略部分逻辑
     continueConsume = ConsumeMessageOrderlyService.this.processConsumeResult(msgs, status, context, this);
    } else {
     continueConsume = false;
    }
   }
  } else {
   //省略部分逻辑
   ConsumeMessageOrderlyService.this.tryLockLaterAndReconsume(this.messageQueue, this.processQueue, 100);
  }
 }
}

上面的代码总结一下,Consumer 消费消息的逻辑如下:

  1. 对 MessageQueueLock 进行加锁,这样就保证只有一个线程在处理当前 MessageQueue。
  2. 从 ProcessQueue 拉取一批消息。
  3. 获取 ProcessQueue 锁,这样保证了只有当前线程可以进行消息处理,同时也可以防止 Rebalance 线程把当前处理的 MessageQueue 移除掉。
  4. 执行消费处理逻辑。
  5. 释放 ProcessQueue 处理锁;6.processConsumeResult 方法更新消息偏移量。

注意:ProcessQueue 中的锁是 ReentrantLock。

3、重试

跟并发消息不一样的是,顺序消息消费失败后并不会把消息发送到 Broker,而是直接在 Consumer 端进行重试,如果重试次数超过了最大重试次数(16 次),则发送到 Broker,Broker 则将消息推入死信队列。如下图:

4、总结

RocketMQ 顺序消息的原理是在 Producer 端把一批需要保证顺序的消息发送到同一个 MessageQueue,Consumer 端则通过加锁的机制来保证消息消费的顺序性,Broker 端通过对 MessageQueue 进行加锁,保证同一个 MessageQueue 只能被同一个 Consumer 进行消费。

根据实现原理可以看到,RocketMQ 的顺序消息可能存在两个坑:

  1. 有顺序性的消息需要发送到同一个 MessageQueue,可能导致单个 MessageQueue 消息量很大,而 Consumer 端消费的时候只能单线程消费,很可能导致当前 MessageQueue 消息积压。
  2. 如果顺序消息 MessageQueue 所在的 broker 挂了,这时 Producer 只能把消息发送到其他 Broker 的 MessageQueue 上,而如果新的 MessageQueue 被其他 Consumer 消费,这样两个 Consumer 消费的消息就不能保证顺序性了。如下图:

Broker1 发生故障,把订单出库的消息发送到了 Broker2,由 Consumer2 来进行消费,消息顺序很可能会错乱。

Spring Boot集成RocketMQ之消息对象序列化 当我们在Spring Boot项目中集成RocketMQ后,只需要在配置文件(application.yml)中添加rocketmq的相关配置,即可使用rocketMQTemplate发送对象消息。登录RocketMq Dashborad查看消息会发现我们的对象消息被序列化成json串。那它是使用哪种json序列化工具的呢?Spring Boot在装配RocketMQTemplate时为我们提供了四种消息对象转换类,当发送消息时依次有序的使用四种消息转换类对消息进行序列化,直到找到一个合适的消息转换类。 阅读详情

相关推荐

MacOS多次踩坑后成功安装Homebrew

来一次性成功安装Homebrew吧 官网提供的安装脚本无法成功安装Homebrew,原因大家都懂的,故采用脚本安装的方式。 下载homebrew的安装脚本brew_install 在Download路径下执行如下脚本 curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install >> brew_install 修改brew_install脚本 修改brew_install脚本。如果你的脚本打开之后是如下

weixin_41847116的博客 1983

RocketMQ的顺序消息(顺序消费)

简单介绍了消息有序性的概念,以及RocketMQ如何实现消息的顺序消费。

终生学习践行者 4万+

JPA - @MappedSuperclass - 基类注解

目录前言代码示例 前言 @MappedSuperclass注解一般作为基类的注解,表眀该类是映射的超类,继承于它的子类实体在映射时会自动添加到子类实体的对应数据库表中,用于共同的属性代码复用和模型分离。 代码示例 BaseEntity.java import lombok.Getter; import lombok.Setter; import javax.persistence.MappedSuperclass; import java.util.Date; @Getter @Setter @Ma

Maggieq8324的博客 2065

RocketMQ的顺序消费

上游系统通过消息队列,发送一个订单的状态操作信息,下游系统如何接受消息,并且需要严格保证订单状态的操作顺序性

maimai1993的博客 1万+

海康读码器上位机开发避坑指南:IDMVS客户端之外,如何用C# SDK搞定扫码、数据比对与实时控制?

本文详细介绍了如何利用海康读码器的C# SDK进行二次开发,实现从基础扫码到复杂工业控制的全流程解决方案。内容涵盖SDK架构解析、多设备管理系统构建、业务逻辑与设备控制实现,以及系统集成与性能优化等关键环节,为工业自动化领域的开发者提供实用指南。

weixin_30642561的博客 550

Multisim14.3中FPGA接口电路设计:原理图项目应用

深入讲解在multisim14.3环境下构建FPGA接口电路的方法,结合原理图设计与项目实践,展现multisim14.3强大的电路仿真能力,提升数字系统开发效率。

weixin_42578963的博客 1157

京东PHP笔试真题复盘:从语言基础到高并发架构的考点全解析

PHP作为Web后端开发的主流语言,其核心价值不仅在于语法灵活,更在于对工程化与高并发场景的支撑能力。理解变量引用、内存回收、设计模式等底层原理,是写出健壮代码的前提;而面对电商级流量,则必须掌握MySQL索引优化、事务隔离级别、Redis缓存策略以及消息队列削峰填谷的协作机制。从数据库分库分表到Nginx与PHP-FPM的联动调优,每一个环节都直接决定系统的稳定性与响应速度。本文以京东PHP笔试真题为线索,系统拆解大厂考察的语言基础、数据库、缓存、队列与系统设计等知识模块,帮助后端开发者建立从原理到实战的

weixin_34026997的博客 235

ICV:Metal Fill Insertion流程

如果不想删除先前加的metal fill,可以使用signoff_create_metal_fill -mode add命令,当使用这个mode后,工具不会fix density问题,哪怕设置了signoff.create_metal_fill.fix_density_errors,设置这个mode后可以使用以下option控制metal fill 的插入。默认情况下,signoff_create_metal_fill是会删掉已经加进去的metal/via fill再重新加的。

m0_61544122的博客 1134

数据库性能优化实战:从慢查询诊断到百万QPS架构演进

数据库性能优化是后端开发与系统架构中的核心课题,其本质在于通过一系列技术手段提升数据存取效率,保障系统在高并发场景下的稳定与响应速度。其原理涉及查询执行计划分析、索引数据结构(如B+树)的有效利用、锁机制与事务隔离级别的合理控制等。优化的技术价值直接体现在降低业务延迟、提升吞吐量(QPS/TPS)、节约硬件成本及改善用户体验上,是支撑业务规模化发展的关键技术保障。典型的应用场景包括电商秒杀、实时数据分析、高并发社交应用等,这些场景都对数据库的读写性能提出了极致要求。本文将以一个真实的老项目性能优化案例为线索

weixin_34198881的博客 297

Allegro172版本如何在联机模式下使用skill文件操作指导

注意:如果下次重新开启Symphony模式的时候可能导致symphony_skill中的文件内容被清空,所以最好将自己常用的skill文件都写到symphony_skill.txt中去,然后做好备份,需要的时候,在开启软件后把文件放到env目录中去。在用Allegeo172版本进行PCB设计的时候,有时会用到Symphony模式进行多人实时在线协同设计,如下图。这个模式设计起来可以提升设计速度,但是也有一个缺陷,就是不能使用skill文件。如下图,当调用skill的时候就会出现如下报错。

weixin_54787054的博客 1586

基于simulink 的不间断电源ups的项目实例

UPS系统的核心组件包括整流器、逆变器、电池管理系统和控制系统。- **Three-Phase Controlled Rectifier**:设置触发角为0度,用于控制整流器的输出电压。- **Three-Phase Inverter**:设置逆变器的输出频率为60Hz,用于将直流电转换为交流电。- **Control System**:编写MATLAB函数,用于监测市电状态并控制各模块的工作模式。- **Step**:设置阶跃时间,例如0.05秒,阶跃前后的值分别为0和1,用于模拟市电中断。

xiaoheshang_123的博客 711

rocketMq实现消费的顺序消费

rocketMq,顺序消费

themessi的博客 2052

【人工智能】全面盘点国内AI九大模型:各擅胜场的智能先锋(豆包、文心一言、讯飞星火、通义千问、Kimi、智谱清言、腾讯元宝、秘塔、天工AI)

追求性价比与全能:选豆包,适合个人与中小企业日常使用;侧重中文创作与理解:选文心一言,文学与商业文案创作首选;需要专业语音交互:选讯飞星火,智能客服、车载场景必备;看重生态与多场景:选通义千问,适配电商、办公等企业需求;处理超长文本任务:选Kimi,文档分析、学术研究的利器;专注深度推理创作:选智谱清言,学术与创意写作的伙伴;依赖腾讯生态协同:选腾讯元宝,日常轻量需求的便捷之选;深耕法律学术领域:选秘塔,专业文本处理的权威工具;布局前沿技术体验:选天工AI,享受接近国际顶尖的智能服务。

奶爸的编程之路,也就一周冷个三天 1121

使用RocketMQ实现消息顺序消费

Broker部署相对复杂,Broker分为Master与Slave,一个Master可以对应多个Slave,但是一个Slave只能对应一个Master,Master与Slave 的对应关系通过指定相同的BrokerName,不同的BrokerId 来定义,BrokerId为0表示Master,非0表示Slave。但如果把问题定位在整个队列中时,不同的消息在不同的队列中,又不能保证消息的有序性,不如消息A到了队列2,消息B到了队列1,消费者先消费了队列1再消费队列2,就不能保证有序性。

威哥爱编程,华为 HDE,鸿蒙极客、优快云博客专家、《鸿蒙 HarmonyOS 5/6 开发之路》系列图书第一作者 4605

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

使用RocketMQ如何保证消息顺序

使用RocketMQ如何保证消息顺序

旷野历程 4827

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

RocketMQ如何实现顺序消费

默认MQ没有实现顺序消费,因为RocketMQ1个topic中有四个队列,且消费是多线程进行消费的。即使队列能够保证先进先出,但是由于多线程CPU执行的随机性,我们无法保证消费的顺序,从而导致了消费的乱序。

youngerxsd的博客 1707

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

RocketMQ结合实际场景顺序消费,它是如何保证顺序消费的?

为了保证消息的顺序性,我们必须保证同一个消息队列在同一时刻只能被消费者组内一个消费者消费,从负载均衡方面,向Broker发起锁定该消息队列的请求,上锁成功则新建一个拉取任务PullRequest,从消息消费方面,批量拉取消息成功后,进行提交消费请求,消息提交到内部的线程池,为了保证消息的顺序性,我们必须为消费队列上锁,来保证同一时刻消费队列只会被线程池中的一个线程消费。

m0_57042151的博客 2211

RocketMQ的顺序消费实现(分区有序、全局有序)

全局有序比较简单,主要控制在于创建Topic指定只有一个队列,同步确保生产者与消费者都只有一个实例进行即可。

yqqの博客 5654

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

顺序消息消费者:RocketMQ 提供了特殊的消费者类型,即顺序消息消费者(Orderly Message Consumer)。顺序消息消费者通过指定消费模式为 Orderly,来保证消息按照发生顺序进行消费。Orderly 模式下,RocketMQ 会将同一个消息队列中的消息按照顺序分发给同一个消费者线程,确保消息的顺序性。单队列顺序消费:在某些场景下,一个 Topic 只有一个消息队列,这时消息的顺序消费就是天然的。消费者按顺序从该队列中拉取消息进行消费,因此可以保证消息的顺序性。

学亮编程手记 1217

RocketMQ快速入门:如何保证消息顺序消费,附带源码分析(八)

顺序消息在金融、电商等场景中被广泛应用,只要业务需求对流程顺序性有严格要求,就有顺序消息的应用之地。因此理解顺序消息的原理和实现路径,是我们学习rocketmq的必经之路。

55555的博客 5961

RocketMQ如何保证消息的顺序性

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

qq_30939943的博客 1793

23. rocketmq顺序消费

之前的文章,都是基于并发消费讲解的,今天来分析一下顺序消费

ZXH240651200的博客 4958

简聊RocketMQ如何确保顺序性

RocketMQ 通过多种机制确保消息的顺序性,其核心原理基于分片(Sharding)和队列(Queue)的单调消费

qq_37679639的博客 3348

【MQ篇】RocketMQ如何保证消息的顺序性

目录1. RocketMQ如何保证消息的顺序性1. 为什么会出现乱序(负载均衡)2. 例子3. 如何解决1. 保证Producer、Queue、Comsumer是一对一对一的关系1. 缺点1. 吞吐量降低2. 有阻塞的风险2. 把需要保持顺序消费的消息放到同一个Queue中,且让同一台机子处理1. 存在的问题3. 使用有序消费的模式 1. RocketMQ如何保证消息的顺序性 1. 为什么会出现乱序(负载均衡) Broker中的每个Topic都有多个Queue,写入消息的时候会平均分配(负载均衡机制,默认

weixin_45325628的博客 6043

RocketMQ如何确保消息的顺序消费

生产端:通过确保特定逻辑标识的消息发送到同一队列。消费端:使用,确保队列内的消息按顺序消费。底层设计:CommitLog 的顺序写和 ConsumeQueue 的顺序索引保证消息的存储顺序。分布式:通过队列锁和负载均衡机制,在分布式场景下也能保证顺序性。

流楚丶格念的博客 1490
上一篇: 最佳实践:MySQL CDC 同步数据到 ES
下一篇: 面经:两年半经验,面10个公司,经28轮面试,拿9个offer,涨麻了!
程序员职业指南
博客等级 码龄4年 2136粉丝 960原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值