RocketMQ 主要特性

RocketMQ 的功能特性

消息

顺序消息
RocketMQ 顺序消息在以下两种情况下会出现短暂乱序:Topic 分区数变化、服务端重启升级。

  • 全局顺序:某个Topic下的所有消息都要保证顺序;适用场景:性能要求不高,所有的消息严格按照 FIFO 原则进行消息发布和消费的场景;
  • 分区顺序:对于指定的一个 Topic,同一个分区内的消息按照严格的 FIFO 顺序进行发布和消费;适用场景:性能要求高,以 sharding key 作为分区字段,在同一个区块中严格的按照 FIFO 原则进行消息发布和消费的场景。
消息类型 是否支持事务消息 是否支持延时消息 性能
无序消息(普通、事务、定时和延时消息) 最高
分区顺序消息
全局顺序消息 一般
  • 普通顺序消息 (Normal Ordered Message):消费者通过同一个消费队列收到的消息是有顺序的,不同消息队列收到的消息则可能是无顺序的;
  • 严格顺序消息(Strictly Ordered Message):消费者收到的所有消息均是有顺序的。严格顺序看起来虽好,实现它可会付出巨大的代价。如果你使用严格顺序模式,Broker 集群中只要有一台机器不可用,则整个集群都不可用。

普通消息

定时消息

事务消息

消费者分类

PushConsumer 推送式消费: 高度封装的消费者类型,消息的获取、状态提交以及消费重试都通过 RocketMQ 的客户端 SDK 完成;

Broker 收到数据后会主动推送给消费端,该消费模式一般实时性较高;

  • 执行结果
      1. 消费成功:返回 ConsumeResult.SUCCESS,表示消息处理成功,服务端按照消费结果更新消费进度;
      1. 消费失败:返回 ConsumeResult.FAILURE,表示消息处理失败,需要根据消费重试逻辑判断是否进行重试消费;
      1. 出现非预期失败:按照消费失败处理
  • 错误使用方式

SimpleConsumer:消息的获取、消费状态提交以及消费重试都是通过消费者业务逻辑主动发起调用完成。

PullConsumer 拉取式消费:主动调用Consumer的拉消息方法从Broker服务器拉消息、主动权由应用控制。一旦获取了批量消息,应用就会启动消费过程。

集群消费 Clustering 和 广播消费 Broadcasting

  • 集群消费模式:相同消费者组的每个消费者平均分摊消息;
  • 广播消费模式:相同消费者组的每个消费者接收全量的消息。

回溯消费

RocketMQ 支持按照时间回溯消费,时间维度精确到毫秒。也就是说 Comsumer 已经消费成功的消息,也支持按照时间维度来回退消费进度。

高性能读写

零拷贝技术

如何解决顺序消费和重复消费?

顺序消费

RocketMQ 在主题上是无序的,只有在队列层面才保证有序。解决方式:将同一语义下的消息放入同一个队列,可以使用 ** Hash 取模法** 来保证消息在同一个队列中。

重复消费

解决方式:幂等,需要消费者实现幂等,对于同一个消息的处理结果,执行多少次都不变。这个就需要根据结合具体的业务场景去实现了,比如可以通过写入 Redis、基于数据库的唯一键 之类的。

消息堆积

  • 生产者生产太快:限流降级,也可以增加消费者实例。需要注意的是,若队列(分区)数量低于消费实例数量,增加消费者实例的同时还需要增加每个主题的队列数量,因为一个队列只会被一个消费者消费;
  • 消费者消费太慢:检查消费者是否有错误,比如某一个线程卡死、出现锁资源不释放等问题
    • 消费方队列分配不均衡:Push消费默认按照分区数和消费实例数进行平均分配,假如有5个分区、4个消费实例,那必定会存在一个消费实例消费两个分区,可能会出现消费堆积;
    • 消费线程阻塞:Push消费中,RocketMQ 会通过异步线程将消息拉到本地缓存中,然后再提交给消费线程去处理。本地缓存队列中,最小的未消费完毕的消息与最大的未消费完毕的消息的位点差距如果超过默认值,会触发限流,客户端会停止拉取消息,导致本地缓存队列中待消费的消息减少,从而消费TPS下降。比如 1000 位点的消息消费地很慢,即使后面的消息都被消费了,当前队列已经更新的位点还是9999,需要限流。解决方式是等待最慢的消息消费结束或者等待其超时被移除。

最佳实践

分区数设置指南

  1. 首先确定业务的峰值TPS(即每秒钟的消息生产数)
  2. 确定客户端单客户端的消费能力(即客户端每秒钟能消费多少消息)
  3. 分区数 = 峰值TPS / 单客户端的消费能力,分区数 >= 消费实例个数

生产者最佳实践

  • 生产者发送方式
    • 同步:等待broker同步返回发送结果,发送时间相对异步发送会高一些;适用于可靠性高场景,如重要的消息通知,短信通知;
    • 异步:异步接收返回结果,发送时间短;适用于对响应时间敏感的业务场景,即发送端不能容忍长时间地等待Broker的响应;
    • 批量:单批次消息不应超过4M;适合小消息批量发送的场景;
    • oneway:无返回结果,消息可能丢失,但发送时间短,为微秒级;适用于不特别关心发送结果的场景,例如日志发送。

消费者最佳实践

  • 订阅组订阅一致性:同一个订阅组下所有的 Consumer 实例,订阅的 Topic 与 Tag 必须完全一致,否则可能导致消息丢失;
  • ConsumeFromWhere设置:新创建的订阅组在首次启动时,需要指定从哪里开始消费,注意仅当订阅组是首次启动时,该配置才会生效,后续再次启动将不会生效。
    • CONSUME_FROM_LAST_OFFSET: 第一次启动从队列的最后位置开始消费
    • CONSUME_FROM_FIRST_OFFSET: 第一次启动从队列的最前位置开始消费,即消费Broker未过期的历史消息;
    • CONSUME_FROM_TIMESTAMP: 第一次启动从指定时间点开始消费
posted @ 2025-08-20 17:44  千千菌  阅读(19)  评论(0)    收藏  举报