消息中间件-RocketMQ
RocketMq
介绍
RocketMq
支持的语言:
JAVA
支持的协议:
TCP
MQTT
架构

特色
- Low Latency
- Finance Oriented
- Industry Sustainable
- Vendor Neutral
- BigData Friendly
- Massive Accumulation
名词
| 名称 | 描述 | 说明 |
|---|---|---|
| Message Model | 消息模型 | RocketMQ主要由 Producer、Broker、Consumer 三部分组成,其中Producer 负责生产消息,Consumer 负责消费消息,Broker 负责存储消息。Broker 在实际部署过程中对应一台服务器,每个 Broker 可以存储多个Topic的消息,每个Topic的消息也可以分片存储于不同的 Broker。Message Queue 用于存储消息的物理地址,每个Topic中的消息地址存储于多个 Message Queue 中。ConsumerGroup 由多个Consumer 实例构成 |
| Producer | 消息生产者 | 负责生产消息,一般由业务系统负责生产消息。一个消息生产者会把业务应用系统里产生的消息发送到broker服务器。RocketMQ提供多种发送方式,同步发送、异步发送、顺序发送、单向发送。同步和异步方式均需要Broker返回确认信息,单向发送不需要 |
| Consumer | 消息消费者 | 负责消费消息,一般是后台系统负责异步消费。一个消息消费者会从Broker服务器拉取消息、并将其提供给应用程序。从用户应用的角度而言提供了两种消费形式:拉取式消费、推动式消费 |
| Topic | 主题 | 表示一类消息的集合,每个主题包含若干条消息,每条消息只能属于一个主题,是RocketMQ进行消息订阅的基本单位 |
| Broker Server | 代理服务器 | 消息中转角色,负责存储消息、转发消息。代理服务器在RocketMQ系统中负责接收从生产者发送来的消息并存储、同时为消费者的拉取请求作准备。代理服务器也存储消息相关的元数据,包括消费者组、消费进度偏移和主题和队列消息等 |
| Name Server | 名字服务 | 名称服务充当路由消息的提供者。生产者或消费者能够通过名字服务查找各主题相应的Broker IP列表。多个Namesrv实例组成集群,但相互独立,没有信息交换 |
| Pull Consumer | 拉取式消费 | Consumer消费的一种类型,应用通常主动调用Consumer的拉消息方法从Broker服务器拉消息、主动权由应用控制。一旦获取了批量消息,应用就会启动消费过程 |
| Push Consumer | 推动式消费 | Consumer消费的一种类型,该模式下Broker收到数据后会主动推送给消费端,该消费模式一般实时性较高 |
| Producer Group | 生产者组 | 同一类Producer的集合,这类Producer发送同一类消息且发送逻辑一致。如果发送的是事务消息且原始生产者在发送之后崩溃,则Broker服务器会联系同一生产者组的其他生产者实例以提交或回溯消费 |
| Consumer Group | 消费者组 | 同一类Consumer的集合,这类Consumer通常消费同一类消息且消费逻辑一致。消费者组使得在消息消费方面,实现负载均衡和容错的目标变得非常容易。要注意的是,消费者组的消费者实例必须订阅完全相同的Topic。RocketMQ 支持两种消息模式:集群消费(Clustering)和广播消费(Broadcasting) |
| Clustering | 集群消费 | 集群消费模式下,相同Consumer Group的每个Consumer实例平均分摊消息 |
| Broadcasting | 广播消费 | 广播消费模式下,相同Consumer Group的每个Consumer实例都接收全量的消息 |
| Normal Ordered Message | 普通顺序消息 | 普通顺序消费模式下,消费者通过同一个消息队列( Topic 分区,称作 Message Queue) 收到的消息是有顺序的,不同消息队列收到的消息则可能是无顺序的 |
| Strictly Ordered Message | 严格顺序消息 | 严格顺序消息模式下,消费者收到的所有消息均是有顺序的 |
| Message | 消息 | 消息系统所传输信息的物理载体,生产和消费数据的最小单位,每条消息必须属于一个主题。RocketMQ中每个消息拥有唯一的Message ID,且可以携带具有业务标识的Key。系统提供了通过Message ID和Key查询消息的功能 |
| Tag | 标签 | 为消息设置的标志,用于同一主题下区分不同类型的消息。来自同一业务单元的消息,可以根据不同业务目的在同一主题下设置不同标签。标签能够有效地保持代码的清晰度和连贯性,并优化RocketMQ提供的查询系统。消费者可以根据Tag实现对不同子主题的不同消费逻辑,实现更好的扩展性 |
应用场景
示例情形
-
simple 简单的消息发布订阅模式
- 多个消费者会均匀消费消息
-
order
- 全局有序
- 分区有序 基于队列实现,相同orderId的有序
-
broadcasting
- 多个消费者都会收到消息(基于tag、expression)
-
schedule
-
batch
-
filter
- 基于SQL表达式过滤
-
logappender
-
openMessaging
+
消息生产
-
消息的分类
- 基于TAG实现消息的分类,只有设置TAG的消息才能根据TAG过滤;环境话说,如果消息没有设置tag,但消费时按照tag过滤,能否收到消息?当然是不能的
-
消息的Key
- 全局消息主键,一般和业务关联,尽量不要重复
-
消息的发送状态
- SEND_OK 只能说明消息发送到Breoker成功,并不能保证消息刷盘或同步Master成功。Broker:ASYNC_MASTER、SYNC_MASTER、SLAVER;刷盘:SYNC_FLUSH、ASYNC_FLUSH
- FLUSH_DISK_TIMEOUT 消息发送成功但是服务器刷盘超时,Broker服务器未在同步刷盘时间内(默认为5s)完成刷盘
- FLUSH_SLAVE_TIMEOUT 消息发送成功,但是服务器同步到Slave时超时返回此状态
- SLAVE_NOT_AVAILABLE 消息发送成功,但是此时Slave不可用。当Broker配置为同步Master时,但没有配置slave Broker服务器返回此状态。
-
消息的重发
- 内部实现
- 至多重试2次
- 同步发送失败时,轮转到下一个Broker,异步发送失败,继续当前Broker重试
- 超时异常,不重发
- 应用层添加重试逻辑。物理存档到DB,定时重发
- 内部实现
-
oneway
- 情形
- 针对消息发送效率与可靠性要求不高的情形。比如日志收集
- 情形
消息消费
-
等幂消费
- 消息的等幂,通过消息id全局唯一来判断
- 业务的等幂,可通过消息key
-
快速消费
- 提高消费并行度
- 同一个 ConsumerGroup 下,通过增加 Consumer 实例数量来提高并行度(需要注意的是超过订阅队列数的 Consumer 实例无效)。可以通过加机器,或者在已有机器启动多个进程的方式。
- 提高单个 Consumer 的消费并行线程,通过修改参数 consumeThreadMin、consumeThreadMax实现
- 批量消费
- 调整consumer参数consumeMessageBatchMaxSize
-
跳过非重要消息
- 优化消费时业务
- 提高消费并行度
-
日志
-
消费者分组
- 比如消费者A订阅TopicA中TagA的消息,当生产者已经生产了TagB的消息,此时修改消费者A的订阅标签为TagB是无法收到消息的,需要同时修改分组,也就是订阅配置信息和消费分组绑定了
配置
-
Broker配置
参数名 默认值 说明 listenPort 10911 接受客户端连接的监听端口 namesrvAddr null nameServer 地址 brokerIP1 网卡的 InetAddress 当前 broker 监听的 IP brokerIP2 跟 brokerIP1 一样 存在主从 broker 时,如果在 broker 主节点上配置了 brokerIP2 属性,broker 从节点会连接主节点配置的 brokerIP2 进行同步 brokerName null broker 的名称 brokerClusterName DefaultCluster 本 broker 所属的 Cluser 名称 brokerId 0 broker id, 0 表示 master, 其他的正整数表示 slave storePathRootDir $HOME/store/ 存储根路径 storePathCommitLog $HOME/store/commitlog/ 存储 commit log 的路径 mappedFileSizeCommitLog 1024 * 1024 * 1024(1G) commit log 的映射文件大小 deleteWhen 04 在每天的什么时间删除已经超过文件保留时间的 commit log fileReservedTime 72 以小时计算的文件保留时间 brokerRole ASYNC_MASTER SYNC_MASTER/ASYNC_MASTER/SLAVE flushDiskType ASYNC_FLUSH SYNC_FLUSH/ASYNC_FLUSH SYNC_FLUSH 模式下的 broker 保证在收到确认生产者之前将消息刷盘。ASYNC_FLUSH 模式下的 broker 则利用刷盘一组消息的模式,可以取得更好的性能。 -
客户端配置
参数名 默认值 说明 namesrvAddr Name Server地址列表,多个NameServer地址用分号隔开 clientIP 本机IP 客户端本机IP地址,某些机器会发生无法识别客户端IP地址情况,需要应用在代码中强制指定 instanceName DEFAULT 客户端实例名称,客户端创建的多个Producer、Consumer实际是共用一个内部实例(这个实例包含网络连接、线程资源等) clientCallbackExecutorThreads 4 通信层异步回调线程数 pollNameServerInteval 30000 轮询Name Server间隔时间,单位毫秒 heartbeatBrokerInterval 30000 向Broker发送心跳间隔时间,单位毫秒 persistConsumerOffsetInterval 5000 持久化Consumer消费进度间隔时间,单位毫秒 -
2 Producer配置
| 参数名 | 默认值 | 说明 |
|---|---|---|
| producerGroup | DEFAULT_PRODUCER | Producer组名,多个Producer如果属于一个应用,发送同样的消息,则应该将它们归为同一组 |
| createTopicKey | TBW102 | 在发送消息时,自动创建服务器不存在的topic,需要指定Key,该Key可用于配置发送消息所在topic的默认路由。 |
| defaultTopicQueueNums | 4 | 在发送消息,自动创建服务器不存在的topic时,默认创建的队列数 |
| sendMsgTimeout | 3000 | 发送消息超时时间,单位毫秒 |
| compressMsgBodyOverHowmuch | 4096 | 消息Body超过多大开始压缩(Consumer收到消息会自动解压缩),单位字节 |
| retryAnotherBrokerWhenNotStoreOK | FALSE | 如果发送消息返回sendResult,但是sendStatus!=SEND_OK,是否重试发送 |
| retryTimesWhenSendFailed | 2 | 如果消息发送失败,最大重试次数,该参数只对同步发送模式起作用 |
| maxMessageSize | 4MB | 客户端限制的消息大小,超过报错,同时服务端也会限制,所以需要跟服务端配合使用。 |
| transactionCheckListener | 事务消息回查监听器,如果发送事务消息,必须设置 | |
| checkThreadPoolMinSize | 1 | Broker回查Producer事务状态时,线程池最小线程数 |
| checkThreadPoolMaxSize | 1 | Broker回查Producer事务状态时,线程池最大线程数 |
| checkRequestHoldMax | 2000 | Broker回查Producer事务状态时,Producer本地缓冲请求队列大小 |
| RPCHook | null | 该参数是在Producer创建时传入的,包含消息发送前的预处理和消息响应后的处理两个接口,用户可以在第一个接口中做一些安全控制或者其他操作。 |
- 3 PushConsumer配置
| 参数名 | 默认值 | 说明 |
|---|---|---|
| consumerGroup | DEFAULT_CONSUMER | Consumer组名,多个Consumer如果属于一个应用,订阅同样的消息,且消费逻辑一致,则应该将它们归为同一组 |
| messageModel | CLUSTERING | 消费模型支持集群消费和广播消费两种 |
| consumeFromWhere | CONSUME_FROM_LAST_OFFSET | Consumer启动后,默认从上次消费的位置开始消费,这包含两种情况:一种是上次消费的位置未过期,则消费从上次中止的位置进行;一种是上次消费位置已经过期,则从当前队列第一条消息开始消费 |
| consumeTimestamp | 半个小时前 | 只有当consumeFromWhere值为CONSUME_FROM_TIMESTAMP时才起作用。 |
| allocateMessageQueueStrategy | AllocateMessageQueueAveragely | Rebalance算法实现策略 |
| subscription | 订阅关系 | |
| messageListener | 消息监听器 | |
| offsetStore | 消费进度存储 | |
| consumeThreadMin | 20 | 消费线程池最小线程数 |
| consumeThreadMax | 20 | 消费线程池最大线程数 |
| consumeConcurrentlyMaxSpan | 2000 | 单队列并行消费允许的最大跨度 |
| pullThresholdForQueue | 1000 | 拉消息本地队列缓存消息最大数 |
| pullInterval | 0 | 拉消息间隔,由于是长轮询,所以为0,但是如果应用为了流控,也可以设置大于0的值,单位毫秒 |
| consumeMessageBatchMaxSize | 1 | 批量消费,一次消费多少条消息 |
| pullBatchSize | 32 | 批量拉消息,一次最多拉多少条 |
- PullConsumer配置
| 参数名 | 默认值 | 说明 |
|---|---|---|
| consumerGroup | DEFAULT_CONSUMER | Consumer组名,多个Consumer如果属于一个应用,订阅同样的消息,且消费逻辑一致,则应该将它们归为同一组 |
| brokerSuspendMaxTimeMillis | 20000 | 长轮询,Consumer拉消息请求在Broker挂起最长时间,单位毫秒 |
| consumerTimeoutMillisWhenSuspend | 30000 | 长轮询,Consumer拉消息请求在Broker挂起超过指定时间,客户端认为超时,单位毫秒 |
| consumerPullTimeoutMillis | 10000 | 非长轮询,拉消息超时时间,单位毫秒 |
| messageModel | BROADCASTING | 消息支持两种模式:集群消费和广播消费 |
| messageQueueListener | 监听队列变化 | |
| offsetStore | 消费进度存储 | |
| registerTopics | 注册的topic集合 | |
| allocateMessageQueueStrategy | AllocateMessageQueueAveragely | Rebalance算法实现策略 |
- Message数据结构
| 字段名 | 默认值 | 说明 |
|---|---|---|
| Topic | null | 必填,消息所属topic的名称 |
| Body | null | 必填,消息体 |
| Tags | null | 选填,消息标签,方便服务器过滤使用。目前只支持每个消息设置一个tag |
| Keys | null | 选填,代表这条消息的业务关键词,服务器会根据keys创建哈希索引,设置后,可以在Console系统根据Topic、Keys来查询消息,由于是哈希索引,请尽可能保证key唯一,例如订单号,商品Id等。 |
| Flag | 0 | 选填,完全由应用来设置,RocketMQ不做干预 |
| DelayTimeLevel | 0 | 选填,消息延时级别,0表示不延时,大于0会延时特定的时间才会被消费 |
| WaitStoreMsgOK | TRUE | 选填,表示消息是否在服务器落盘后才返回应答。 |
问题
-
消费分组
+ 消费者相同分组名,不同Topic,消息消费失败问题
+ 同一分组下的消费者,只能同时消费同一个Topic下的不同队列的消息 -
消息队列
+ topic和queue都是逻辑上的概念,消息最终都是存储到commitLog,目的是为了更细粒度区分消息
+ 同一个队列只会绑定到一个消费者上 -
偏移量
注意事项
- 注意分组类似一个集群,需要保证其发送或接收消息的一致性。比如同一个分组内的消费者接收不同topic的消息,这样会导致消息消费失败,因为topic绑定分组进行消息投递,但是由于消费者topic不一致最终大致消息没有被消费。
1、https://rocketmq.apache.org/docs

浙公网安备 33010602011771号