1. 单机模式的瓶颈在哪里:先说清楚为什么要搭集群
RocketMQ 作为生产环境中大规模使用的消息中间件,很多团队一开始都是从单机开始的,部署简单、配置少、出问题排查也容易。但只要你把 RocketMQ 真正放到业务流量里跑上几个月,就会慢慢发现单机模式的几个硬伤。
首先是单点故障。Broker 只有一台,一旦这台机器磁盘满了、内存溢出、进程被 OOM Kill,或者机房断电,整个 Broker 就不可用了。Producer 还能继续发消息,但消息会一直重试直到发送超时;Consumer 端消息直接拉不到,业务链路瞬间卡住。更难受的是,如果这台机器物理损坏,CommitLog 里的存量消息可能全丢,连补偿的机会都没有。
其次是容量和性能的天花板。单台 Broker 的写入能力取决于 CPU、内存和磁盘 IO,即使你配了 SSD,单机写入 TPS 到了某个量级之后很难再往上走。而且 RocketMQ 的消息存储文件是顺序追加写的,单机磁盘空间一旦用尽,Broker 会直接拒绝写入,触发快速失败保护机制。业务量上涨之后,你想通过加配置来扛,撑不了多久。
第三是故障恢复缺乏自动化。单机模式下 Broker 挂了,你得手动重启、手动恢复,整个过程至少几分钟到几十分钟。对核心链路来说,这几分钟就是生产事故。
集群能解决的就是这三个核心问题:高可用(一台挂了有备机接管)、水平扩展(加 Broker 机器就能扛更多流量)、故障转移(某台 Master 宕机后,消费者还能从其他 Broker 或 Slave 上拉消息,业务不中断)。
所以在决定要不要搭集群、搭哪种集群之前,先想清楚一个问题:你的 RocketMQ 承载的流量链路,能容忍多长时间的不可用?容忍时长决定了你要选哪种高可用方案。后面章节我会把几种主流集群模式的差异和部署细节全部拆开讲。
2. 集群架构的核心组成:NameServer 与 Broker 的协作方式
RocketMQ 集群里最核心的两个角色是NameServer和Broker,理解它们各自干什么、怎么配合,比死记配置项重要得多。
2.1 NameServer:轻量级路由中心,但不像你想象的那样复杂
NameServer 的作用是维护 Broker 的路由信息,包括 Broker 的地址、存活状态、Topic 配置等。Producer 发消息之前先找 NameServer 拿 Broker 地址,Consumer 拉消息之前同样要先问 NameServer 要路由。
很多人第一次接触 RocketMQ 集群,误以为 NameServer 是像 ZooKeeper 那样的强一致性注册中心。实际不是。NameServer 之间是互相独立的,没有数据同步,也用不着部署成对等集群来搞选举。它就是一个轻量的、保证"最终一致"的路由表存储节点。多台 NameServer 部署在一起,只是为了不单点,Producer 和 Consumer 会同时向所有 NameServer 发起请求,谁可用就用谁。
我在实际部署中,习惯至少部署 2 台 NameServer,最好是奇数台,比如 3 台。虽然它不选举,但奇数台在运维上更规整,而且每一台的 broker 路由信息都是全量的,即使挂掉一台,剩下的还能正常提供服务。NameServer 本身非常轻量,内存占用大约几百 MB 到 1 GB 左右,建议和 Broker 分离部署,避免 Broker 把内存吃满之后把 NameServer 也拖垮。
2.2 Broker:真正存储消息的地方,Master 和 Slave 的分工
Broker 才是真正干活的节点,消息的存储和读写全在 Broker 上完成。Broker 的角色分为 Master 和 Slave,每个 Broker 需要有一个唯一的brokerName,同一个 brokerName 下的 Master 和 Slave 构成一个Broker 组。
Master 负责处理写入请求和读取请求,Slave 负责从 Master 同步数据,并在 Master 不可用时承担读取任务。同步方式有两种,一种叫同步复制,一种叫异步复制,两者的差异我放到第三章详细对比,这里先记住这个概念。
Broker 在启动时会向所有的 NameServer 注册自己的元数据,包括 brokerName、brokerId(0 表示 Master,非 0 表示 Slave)、IP 地址、端口号等等。NameServer 拿到这些信息后,就为 Producer 和 Consumer 提供路由查询服务。
2.3 一条消息从发送到消费,集群里发生了什么
我用一个完整的流程把集群协作串起来,这样你理解起来更直观:
- 多个 Broker 启动后,各自向 NameServer 注册自己的信息,并开启心跳上报。
- Producer 启动时,先从 NameServer 拉取 Topic 的路由信息,然后选择一台 Broker 发送消息。
- Broker 收到消息后,将消息顺序写入 CommitLog 文件,同时构建 ConsumeQueue 索引,并返回写入结果给 Producer。
- Consumer 启动后,同样从 NameServer 拉取路由信息,找到目标 Broker,主动拉取消息进行消费。
- 如果某台 Broker 宕机,NameServer 会在一定时间内(默认 10 秒)检测不到心跳,就会把这个 Broker 的路由信息剔除,客户端下次拉取路由时就会避开这台故障 Broker。
这里有一个容易踩坑的地方:NameServer 剔除故障 Broker 的时间并不是即时的,它有一个扫描周期。默认情况下,NameServer 每隔 10 秒扫描一次 Broker 列表,判断是否有 Broker 长时间没有上报心跳。也就是说,一台 Broker 物理宕机之后,客户端可能需要 10 到 30 秒才能感知到并切换路由。对于要严格控制故障转移时间的业务来说,这个默认值偏长,可以通过调整 NameServer 端的scanPeriod和 Broker 端的心跳间隔来缩短感知时间。不过在调参之前,你要先想清楚,频繁的扫描和心跳检查在高并发场景下会带来额外的网络开销,不要盲目追求极致的故障感知速度。
3. 四种集群模式逐一拆解:从单 Master 到 Dledger 自动选主
RocketMQ 官方的集群模式有四种,很多新手查资料容易看混,我在这里把它们放在一起对比,同时把适合的场景说清楚。
3.1 单 Master 模式:入门可以,生产慎用
这是最简单的一种部署,只有一个 Broker 角色,不区分 Master 和 Slave。所有消息都在这一个 Broker 上存储和读写。
这种模式的好处是部署极简,适合本地开发、功能测试、学习体验。缺点是单点,Broker 挂了整个消息链路就断了,没有备机可以顶上。数据可靠性也只能依赖这块磁盘,磁盘坏了数据就丢了。如果你的业务还处在 POC(概念验证)阶段,可以用单 Master;如果已经开始有真实用户流量,我不建议你用这个模式扛生产。
3.2 多 Master 模式:无 Slave,Broker 之间互备
这种模式下,集群中有多台 Broker,每台都是 Master,没有 Slave。架构上不存在主从关系,每台 Broker 独立承担一部分 Topic 的存储和读写。如果你在集群里配置了多个 brokerName,每个 brokerName 下面是单个 Master,这就是多 Master 模式。
优点:
- 没有主从同步的开销,写入性能是最高的。
- 某台 Broker 挂了,其他 Broker 上的 Topic 还能继续服务,不会全集群瘫痪。
缺点:
- 挂掉的那台 Broker 上的未消费消息,在它恢复之前是读不了的,消费者只能等 Broker 重启。
- 数据只有一份,如果机器损坏,消息会丢失。
适合对性能要求极高、但对单点故障容忍度较高的场景,比如部分日志类数据、非核心异步通知等。说实话,在业务量大且核心的生产环境,多 Master 模式已经不太够用了。
3.3 多 Master 多 Slave 模式:生产最常用的配置
在多个 Master 的基础上,给每个 Master 配一个或多个 Slave,就形成了多 Master 多 Slave 模式。消息先写入 Master,Master 再把数据复制到 Slave。
这种模式下,每个 Broker 组内部有主从关系,Broker 组之间是互相独立、相互备份的。根据复制方式的不同,又分为两种:
异步复制(ASYNC_MASTER)
Master 写入消息成功后,立即向 Producer 返回成功,Slave 异步从 Master 拉取数据。这种方式主从有短暂的延迟,极端情况下如果 Master 写完之后立刻宕机,还没来得及同步的数据会丢。
同步复制(SYNC_MASTER)
Master 必须把消息写入到 Master 和 Slave 都成功之后,才向 Producer 确认成功。这种方式数据可靠性大幅提升,但写入延迟会变高,因为多了一次跨节点的同步等待。
在实际生产里,如果你的业务对消息不能丢敏感(比如交易订单、支付结果通知),至少要用同步复制;如果只是日志推送、非核心通知,异步复制配一个 Slave 也能满足 HA 需求。
3.4 Dledger 模式:基于 Raft 协议的自动故障切换
Dledger 是 RocketMQ 在 4.5 版本之后引入的基于 Raft 协议的存储模式,它的核心价值是实现了 Broker 的自动选主和故障切换,不需要人工干预。
在没有 Dledger 的普通主从模式下,Master 挂了,Slave 只是能读,不能自动变成新的 Master,需要你手动去改配置、重启 Broker,把 Slave 提升为 Master。整个过程不仅繁琐,而且在业务流量大的时候,几分钟的人工切换时间里消息收发受到很大影响。
Dledger 用 Raft 协议管理 Broker 组里的多台节点,节点之间会通过投票选出 Leader(相当于 Master),其他节点是 Follower(相当于 Slave)。当 Leader 宕机之后,Follower 之间会重新发起选举,自动选出新的 Leader,整个过程不需要人工介入。
Dledger 模式下,RocketMQ 数据库引用了一个新的名词:RAFFile。实际上它改变的是消息存储层的复制协议,对上层业务透明,Producer 和 Consumer 无需感知 Leader 切换。部署上,一个 Dledger 节点组通常至少需要 3 台 Broker(保证选主过半数)。如果你的团队运维能力强、追求自动化故障转移,Dledger 模式是目前比较理想的选择。
| 模式 | Master 数量 | Slave 数量 | 故障转移方式 | 数据可靠性 | 适合场景 |
|---|---|---|---|---|---|
| 单 Master | 1 | 无 | 无 | 低 | 开发测试 |
| 多 Master | 2+ | 无 | 手动切换 | 低 | 日志、非核心异步 |
| 多 Master 多 Slave(异步) | 2+ | 每个 Master 至少 1 个 | 手动切换 | 中 | 普通业务、可容忍少丢 |
| 多 Master 多 Slave(同步) | 2+ | 每个 Master 至少 1 个 | 手动切换 | 高 | 订单、支付等核心链路 |
| Dledger | 3+ 节点组 | 自动选举 | 自动 | 高 | 要求自动故障转移的核心业务 |
4. 多 Master 多 Slave(异步复制)模式的生产级部署实录
这一节我以实际生产环境为例,完整走一遍多 Master 多 Slave(异步复制)的部署过程,包含环境规划、配置参数、启动顺序和验证手段。这套方案在大多数业务场景下足够用,也是我目前最推荐中小团队上手的配置。
4.1 服务器规划与前置条件
以一个 2 Master 2 Slave 的最小高可用集群为例,你需要 4 台机器:
| 节点 | 角色 | IP 示例 | 配置建议 |
|---|---|---|---|
| nameserver-1 | NameServer | 10.0.0.11 | 2C4G,内存建议 4G+ |
| nameserver-2 | NameServer | 10.0.0.12 | 2C4G,内存建议 4G+ |
| broker-a-master | Master(broker-a) | 10.0.1.11 | 4C8G,磁盘 100G+ SSD |
| broker-a-slave | Slave(broker-a) | 10.0.1.12 | 4C8G,磁盘 100G+ SSD |
| broker-b-master | Master(broker-b) | 10.0.1.13 | 4C8G,磁盘 100G+ SSD |
| broker-b-slave | Slave(broker-b) | 10.0.1.14 | 4C8G,磁盘 100G+ SSD |
如果你机器资源紧张,NameServer 和 Broker 可以先合部署,但生产环境我强烈建议分开,尤其是 Broker 的磁盘 IO 压力大,不应影响 NameServer 的心跳和路由管理。
操作系统建议 CentOS 7.x 或 Ubuntu 20.04+,JDK 必须用64 位 JDK 1.8 以上,推荐 OpenJDK 1.8 或 11。RocketMQ 4.9.x 系列对 JDK 1.8 兼容性最稳,如果你用的版本在 5.0 以上,建议配合 JDK 11 使用,避免某些新特性在旧 JDK 上出现兼容问题。
4.2 核心配置文件详解
RocketMQ 的 Broker 配置文件默认放在conf/目录下,不同模式对应不同模板。在这里我直接用命令行参数指定方式,但为了好维护,还是建议你把配置写到文件里,然后通过-c参数指定。
以一个 Master 的配置为例,文件broker-a.properties:
# 集群名称,所有 Broker 必须一致 brokerClusterName=DefaultCluster # 这个 Broker 组的名称,同一个组的主从必须一致 brokerName=broker-a # 0 表示 Master,非 0 表示 Slave brokerId=0 # NameServer 地址,多个之间用分号隔开 namesrvAddr=10.0.0.11:9876;10.0.0.12:9876 # 消息存储路径,确保目录存在且有权限 storePathRootDir=/data/rocketmq/store/broker-a-master storePathCommitLog=/data/rocketmq/store/broker-a-master/commitlog # Broker 对外提供服务的 IP brokerIP1=10.0.1.11 # 监听端口 listenPort=10911 # 自动创建 Topic 开关,生产环境建议 true autoCreateTopicEnable=true # 自动创建消费组开关 autoCreateSubscriptionGroup=true # 文件刷盘方式,同步刷盘更安全 flushDiskType=SYNC_FLUSH # 主从复制方式,这里是异步复制 brokerRole=ASYNC_MASTER对应的 Slave 配置broker-a-s.properties:
# 同一个集群 brokerClusterName=DefaultCluster # 同一个 Broker 组 brokerName=broker-a # Slave,非 0 即可,通常用 1 brokerId=1 namesrvAddr=10.0.0.11:9876;10.0.0.12:9876 storePathRootDir=/data/rocketmq/store/broker-a-slave storePathCommitLog=/data/rocketmq/store/broker-a-slave/commitlog brokerIP1=10.0.1.12 listenPort=10911 autoCreateTopicEnable=true autoCreateSubscriptionGroup=true flushDiskType=SYNC_FLUSH # Slave 的角色 brokerRole=SLAVEbroker-b 的配置就是把 brokerName 改成 broker-b,brokerId 0/1,IP 改成 10.0.1.13 和 10.0.1.14 即可。注意每个 Broker 的存储路径要独立,不能共用一个目录。
这里有几个关键的配置点需要说明:
- brokerClusterName 必须一致,否则不同机器之间会被认为是不同的集群,路由信息会乱。
- 同一个 brokerName 下的主从,brokerId 是唯一的,Master 固定为 0,Slave 从 1 开始递增。
- brokerIP1 要写对,特别是在多网卡环境中,如果不显式指定,RocketMQ 会自动识别一个内网 IP,可能导致生产客户端无法连通。
- flushDiskType 和 brokerRole 根据你的可靠性要求来调,生产核心业务建议 SYNC_FLUSH,能防掉电丢消息。
4.3 启动顺序与常用命令
整个启动顺序有个基本原则:先启 NameServer,再启 Broker。Broker 启动时需要向 NameServer 注册,所以 NameServer 必须保证可用。
- 启动 NameServer:
# 在 10.0.0.11 和 10.0.0.12 上执行 nohup sh mqnamesrv > /data/rocketmq/logs/namesrv.log 2>&1 &- 确认 NameServer 启动成功,查看日志:
tail -f /data/rocketmq/logs/namesrv.log # 看到 "The Name Server boot success" 代表成功- 启动 Master(broker-a 的 Master 节点):
nohup sh mqbroker -c /data/rocketmq/conf/broker-a.properties > /data/rocketmq/logs/broker-a-master.log 2>&1 &- 启动 Slave(broker-a 的 Slave 节点):
nohup sh mqbroker -c /data/rocketmq/conf/broker-a-s.properties > /data/rocketmq/logs/broker-a-slave.log 2>&1 &启动 broker-b 的 Master 和 Slave,步骤同上,换成对应配置文件即可。
查看集群状态:
cd /data/rocketmq/bin sh mqadmin clusterList -n 10.0.0.11:9876输出格式类似这样:
#Cluster Name #Broker Name #BID #Addr #Version DefaultCluster broker-a 0 10.0.1.11:10911 V4_9_4 DefaultCluster broker-a 1 10.0.1.12:10911 V4_9_4 DefaultCluster broker-b 0 10.0.1.13:10911 V4_9_4 DefaultCluster broker-b 1 10.0.1.14:10911 V4_9_4BID 为 0 的是 Master,非 0 的是 Slave。看到这套信息,说明你的 Multi Master 集群已经正常工作了。
4.4 部署 Dashboard 监控控制台
RocketMQ 官方提供了一个 Web 控制台项目,叫 RocketMQ Dashboard,可以查看集群状态、Topic 数据、消费进度和消息轨迹。部署方式有几种,我常用的是用 Docker 跑一份,简单省事:
docker run -d \ --name rocketmq-dashboard \ -e NAMESRV_ADDR=10.0.0.11:9876;10.0.0.12:9876 \ -e JAVA_OPTS="-Drocketmq.namesrv.addr=10.0.0.11:9876;10.0.0.12:9876" \ -p 8080:8080 \ apacherocketmq/rocketmq-dashboard:latest登录界面之后,可以重点查看这几个页面:
- 集群页面:确认所有 Broker 都在线,主从关系正确。
- Topic 页面:查看主题的路由分布是否均匀。
- 消费者页面:检查消费组是否有堆积、延迟情况。
Dashboard 本身不参与消息链路,挂了不影响业务,但建议至少部署一份用于日常巡检。生产环境把 Dashboard 的端口限制在内网,不要直接暴露公网。
5. 部署验证与常见故障排查实操
集群部署起来只是第一步,真正考验人的是后续的验证和排障。这一节我把我在实践中遇到的典型问题和对应排查思路完整列出来。
5.1 集群是否真的高可用?做个故障演练
最直接的办法就是主动 kill 某一个 Master 进程,然后观察生产端的表现:
# 在 broker-a-master 机器上执行 kill -9 $(pidof java)然后立即用 mqadmin 查看集群状态:
sh mqadmin clusterList -n 10.0.0.11:9876你能看到 broker-a 的 Master 已经不在列表里,但 Slave 还在。此时,如果消费者有配置 slaveReadEnable(默认在 4.9.x 后的版本需要显式打开,老版本默认可以从 Slave 读),消息读取可以从 Slave 继续;否则消费者会一直尝试连接 Master,直到 Master 恢复。
这就是为什么我建议你在 consumer 的相关配置里,把slaveReadEnable设为 true,至少在运维层面留一条冗余读路径:
consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET); consumer.setMessageModel(MessageModel.CLUSTERING);实际上这是 JVM 参数层面的调整,在 client 端没有太直接的开关,更常见的做法是配置 Broker 端的slaveReadEnable=true(在 broker 配置文件中设置,默认在较新版本中已开启)。这一点比较容易在文档里被忽略,但故障场景下很有用。
5.2 客户端连不上集群的排查链路
这是新手最容易遇到的问题,现象是 Producer 报connect to 10.0.1.11:10911 failed。排查顺序我建议按照下面的链路走:
- 先确认 NameServer 还能不能 ping 通,
telnet 10.0.0.11 9876检查端口连通性。 - 再确认 Broker 进程是否存活,
jps看有没有 BrokerStartup 进程。 - 查看 Broker 日志,如果发现
register broker to name server failed,基本是 NameServer 地址配置错误或者网络不通。 - 检查 Broker 的
brokerIP1是否配置成客户端可达的 IP。这在云环境尤其是多网卡场景特别常见,Broker 默认会取第一块网卡的 IP,客户端根本访问不到。 - 再看防火墙和安全组,生产环境经常是安全组里没有放开 10911 端口,客户端永远连不上。
最后的兜底手段:用mqadmin sendMessage命令直接向某个 Topic 发一条测试消息,能发通就说明链路是通的,能大幅缩小排查范围。
sh mqadmin sendMessage -n 10.0.0.11:9876 -t TestTopic -p "hello message"如果命令报错,错误信息会直接指出是 NameServer 不可达,还是 Broker 不存在,还是路由没有。
5.3 自动创建 Topic 的隐藏坑:VIP 通道
有个非常经典的问题:RocketMQ 发送消息时默认会走一个 VIP 通道,端口是 Broker 端口基础上减 2。比如 Broker 监听 10911,客户端默认会尝试连 10909。如果你没有在安全组里开放 10909 端口,就会出现一个诡异的现象——用命令行工具测试可以,但用 java client 发送一直超时。
解决办法:在客户端指定:
producer.setSendLatencyFaultEnable(false);或者把 broker 配置中的brokerVIPSupportEnable设为 false。很多生产事故的排查最终都绕回到这个点上,建议你在部署文档里直接写清楚:安全组需要放行 Broker 监听端口、VIP 端口(监听端口减 2)、以及 NameServer 的 9876 端口。
5.4 主从切换的正确操作姿势
Dledger 模式自动选举不需要你操心,但普通多 Master 多 Slave 模式下,Master 挂了之后你要手动把 Slave 提升为新的 Master。具体操作方式网上说法很多,最稳妥的做法是:
- 停止这台 Slave 的 Broker 进程。
- 修改配置,把 brokerId 改为 0,brokerRole 改为 ASYNC_MASTER。
- 使用新的配置重启 Broker。
这里仅提供一种可行的方式,实际操作中涉及的数据补救和消息追平逻辑,根据你的实际架构和版本需要做充分测试。Dledger 模式之所以受欢迎,能省掉这些繁琐的人工步骤是一个很大原因。
6. 生产环境选型建议:你的业务到底适合哪种集群
网上关于 Kafka、RabbitMQ、RocketMQ 的选型对比很多,这里我不重复,单从 RocketMQ 三种主要集群模式的选型角度给你一些实际建议。
6.1 中小团队、业务初期、单机房
建议配置:2 个 NameServer + 2 Master 2 Slave(异步复制)。这个配置成本不高,机器大约 4 到 6 台,能扛住每秒几千条的写入,架构清晰,出问题手动切换也能接受。如果你的业务还没到大规模用户量,先不要急着上 Dledger,因为 Dledger 的运维门槛和维护成本更高,团队如果对 Raft 不熟悉,遇到问题反而更难排查。
6.2 核心交易链路、消息不能丢
建议配置:2 个 NameServer + 2 Master 2 Slave(同步复制)+ Dashboard 监控。同步复制确保 Master 和 Slave 都写成功才返回,消息基本不丢。刷盘也要配合使用 SYNC_FLUSH,这是磁盘存储层的最后一道保险。在压测阶段要重点观察同步复制带来的延迟变化,RocketMQ 同步复制通常能控制在毫秒级,但网络抖动会放大延迟,所以集群机器之间尽量走同机房低延时网络。
6.3 要求自动故障转移、运维人力有限
建议配置:2 个 NameServer + 3 节点 Dledger 组。这是我个人对运维团队规模较小、但业务重要性高的团队比较推荐的方案。自动选主可以避免人工切换的滞后和误操作,而且 Dledger 模式下客户端不需要感知 Master 切换,对业务无侵入。代价是存储和网络开销比普通主从模式大一些,3 个节点中最少也要多数派(2 个)正常工作才能选主,所以挂 1 台没事,挂 2 台就不可用了。
6.4 多机房容灾
如果你的业务有多机房需求,简单的 RocketMQ 集群不够,还需要考虑跨机房的消息同步。常见方案是独立机房各自部署一套集群,通过 MirrorMaker 等同步工具做消息复制,或者在上层业务做双写。这个话题展开讲又是一篇长篇,但核心思路是:集群内高可用、集群间数据双活,两者是不同层次的问题,不要混在一起设计。
7. 部署踩坑后的几点实在总结
最后分享几个我实际部署 RocketMQ 集群以来的真实感受,希望对你有用。
第一,配置文件的命名和路径一定要规范。broker-a.properties、broker-b.properties,不要用 test1、test2 这种名字,否则几个月之后你根本分不清哪个 Broker 在跑哪份配置,尤其是做故障切换的时候,简直灾难。
第二,日志和存储路径要提前规划好。RocketMQ 的日志默认会输出到启动目录下,我见过不少团队因为没指定-Drocketmq.client.logRoot和 ROCKETMQ_HOME,导致日志散落各处,最后排查问题无从下手。建议所有 Broker 统一用一个日志目录,并在部署脚本里固定。
第三,启动之前用ulimit -n把文件句柄数调大。RocketMQ 的 Broker 会打开大量文件,默认的 1024 限制在生产环境必炸。在/etc/security/limits.conf里给启动用户加一句* soft nofile 655350,重启进程后ulimit -n确认生效。
第四,JVM 参数不要直接跑默认值。RocketMQ 官方脚本默认的堆内存可能偏大或偏小,要根据你的机器规格调整。我一般建议 Broker 进程堆内存设置在 4G 到 8G 左右,同时留足堆外内存给 PageCache,因为 RocketMQ 大量依赖操作系统的页缓存来做消息读写加速。JVM 配置不合理,内存和性能都会出问题。
第五,消费堆积一定要有指标告警。集群搭得再好,如果消费速度跟不上生产速度,消息堆积会拖垮整个链路。Dashboard 里的消费者页面能看到堆积量,但建议你在监控系统里对ConsumerLag设置阈值告警,达到阈值就提醒,不要等业务方反馈才去查。
RocketMQ 集群部署本身并不复杂,复杂的是对架构原理的理解和故障场景下的快速定位能力。希望这篇文章能帮你把集群的骨架搭起来,并且知道出了问题该往哪查。如果你的业务量还在起步阶段,完全可以先用多 Master 多 Slave 模式跑起来,等确实需要自动切换了,再平滑演进到 Dledger 模式,这个升级路径 RocketMQ 是支持的,不必一开始就把所有高可用方案全部铺上。