avatar

Ryan's Blog

The first step is always the hardest.

  • 首页
  • 分类
  • 标签
  • 归档
  • 关于
  • 工具
Home RocketMQ DLedger 高可用集群搭建与故障排查:自动选主、Docker 网络与常见踩坑
文章

RocketMQ DLedger 高可用集群搭建与故障排查:自动选主、Docker 网络与常见踩坑

Posted 2021-11-25 Updated 16 days ago
By Ryan Chen
28~36 min read

RocketMQ 早期常见高可用方案是主从复制,但传统主从模式下 Master 故障后往往需要人工介入。RocketMQ-on-DLedger 通过 Raft 复制和自动选主能力,让一组 Broker 可以在 Leader 故障后自动选出新的 Leader,从而提升可用性。

这篇文章整理 RocketMQ 4.x DLedger 集群的搭建思路、关键配置、Docker 网络踩坑、自动选主验证和常见故障排查。需要注意:RocketMQ 5.x 之后官方更强调 Controller 模式实现自动主从切换,DLedger 方案与 5.x Controller 方案需要区分理解。

如果你想了解 RocketMQ 架构和 Broker / NameServer / Topic 等基础概念,可以先看:RocketMQ 架构设计与应用最佳实践:高可用消息队列核心解析。

RocketMQ 高可用方案演进

RocketMQ 常见高可用方案可以粗略分为:

方案 特点 说明
主从同步 / 异步复制 架构简单 Master 故障后需要处理主从切换
DLedger 基于 Raft 自动选主 RocketMQ 4.x 常见自动容灾方案
Controller 模式 RocketMQ 5.x 自动主从切换方案 更符合 5.x 高可用演进方向

本文重点是 RocketMQ 4.x DLedger 模式。

DLedger 是什么

RocketMQ-on-DLedger Group 是一组相同 Broker Name 的 Broker 节点,通常至少 3 个节点,通过 Raft 自动选举 Leader,其余节点作为 Follower。消息数据在 Leader 和 Follower 之间复制,以保证高可用。

核心特点:

  • 至少 3 节点,满足多数派。
  • Leader 负责写入。
  • Follower 复制日志。
  • Leader 故障后自动选主。
  • 同一个集群可以部署多个 DLedger Group,实现水平扩展。

为什么不建议 2 节点?因为 Raft 需要多数派。2 节点场景下,如果 Leader 故障,只剩 1 个节点无法获得过半投票,无法正常选出新 Leader。

集群架构规划

示例规划 3 台机器:

节点 IP 角色
node-0 172.16.0.4 DLedger 节点 n0
node-1 172.16.0.17 DLedger 节点 n1
node-2 172.16.0.14 DLedger 节点 n2

端口建议:

端口 作用
9876 NameServer
10911 Broker remoting 端口
10909 Broker fast remoting 端口,常见为 listenPort - 2
40911 DLedger 节点通信端口,示例值

生产环境要确保这些端口在节点之间互通。

关键配置说明

典型 DLedger Broker 配置:

brokerClusterName=RaftCluster
brokerName=RaftNode00
namesrvAddr=172.16.0.4:9876;172.16.0.17:9876;172.16.0.14:9876
listenPort=10911
brokerIP1=172.16.0.4
storePathRootDir=/opt/rocketmq/store/node00
storePathCommitLog=/opt/rocketmq/store/node00/commitlog
enableDLegerCommitLog=true
dLegerGroup=RaftNode00
dLegerPeers=n0-172.16.0.4:40911;n1-172.16.0.17:40911;n2-172.16.0.14:40911
dLegerSelfId=n0
sendMessageThreadPoolNums=4

关键配置解释:

配置 作用 注意事项
brokerClusterName RocketMQ 集群名 同一集群保持一致
brokerName Broker 组名 同一 DLedger Group 中保持一致
namesrvAddr NameServer 地址 多个用分号分隔
listenPort Broker 对外通信端口 客户端和 Dashboard 要能访问
brokerIP1 Broker 注册到 NameServer 的 IP Docker 部署时非常关键
storePathRootDir 存储根目录 必须持久化
storePathCommitLog commitlog 目录 建议使用高性能磁盘
enableDLegerCommitLog 是否开启 DLedger 必须为 true
dLegerGroup DLedger 组名 同组保持一致
dLegerPeers DLedger 节点列表 n0/n1/n2 与 IP/端口要正确
dLegerSelfId 当前节点 ID 每个节点必须唯一

三台机器的配置大部分一致,主要差异是:

  • brokerIP1
  • storePathRootDir
  • storePathCommitLog
  • dLegerSelfId

宿主机部署思路

宿主机部署通常更直接,网络问题少。大致流程:

  1. 下载 RocketMQ 4.x 二进制包。
  2. 解压到各节点。
  3. 修改 conf/dledger/ 下的配置文件。
  4. 启动多个 NameServer。
  5. 启动 3 个 DLedger Broker。
  6. 创建 Topic。
  7. 发送和消费消息验证。
  8. 停掉 Leader 验证自动选主。

启动 NameServer:

nohup sh bin/mqnamesrv > /opt/rocketmq/logs/namesrv.log 2>&1 &

启动 Broker:

nohup sh bin/mqbroker -c conf/dledger/broker-n0.conf > /opt/rocketmq/logs/broker.log 2>&1 &

其他节点分别使用 broker-n1.conf、broker-n2.conf。

Docker 部署踩坑

原实践中最大的坑是 Docker 默认 bridge 网络。

如果直接使用默认 bridge,Broker 可能把容器内部 IP 注册到 NameServer,例如:

172.17.0.11:10911

此时外部客户端或 Dashboard 会从 NameServer 拿到这个地址,然后连接失败:

org.apache.rocketmq.remoting.exception.RemotingConnectException: connect to <172.17.0.11:10911> failed

原截图保留如下:

RocketMQ bridge 网络连接失败

RocketMQ Dashboard 连接异常

为什么 bridge 网络容易出问题

RocketMQ 客户端访问 Broker 的流程大致是:

  1. 客户端连接 NameServer。
  2. 客户端查询 Topic 路由。
  3. NameServer 返回 Broker 地址。
  4. 客户端连接 Broker 发送或消费消息。

如果 Broker 注册到 NameServer 的地址是容器内部 IP,客户端在容器外部就无法访问。

解决思路:

  • 使用 host 网络。
  • 正确配置 brokerIP1 为宿主机可访问 IP。
  • 正确映射 Broker 端口和 DLedger 端口。
  • 确保防火墙和安全组放行。

Docker host 网络方案

示例:

cname="rocketmq-node1"
logs="/opt/data/${cname}"

mkdir -p ${logs}

docker run -d \
  --name ${cname} \
  --restart=always \
  --privileged=true \
  --net=host \
  -v /opt/rocketmq/rocketmq-4.9.1:/usr/local/rocketmq \
  -v ${logs}:/opt/data \
  your-jdk-image:latest

进入容器后启动 NameServer 和 Broker:

cd /usr/local/rocketmq
nohup sh bin/mqnamesrv > /opt/data/namesrv.log 2>&1 &
nohup sh bin/mqbroker -c conf/dledger/broker-n0.conf > /opt/data/broker.log 2>&1 &

host 网络的优点是简单,Broker 注册宿主机 IP 更直接。缺点是端口隔离弱,多个容器不能使用相同端口。

brokerIP1 与端口说明

Docker 部署时建议显式配置:

brokerIP1=172.16.0.4
listenPort=10911

否则 RocketMQ 可能自动选择容器内 IP 或不符合预期的网卡 IP。

需要确保以下地址对客户端可达:

  • brokerIP1:10911
  • brokerIP1:10909
  • DLedger 节点之间的 40911
  • NameServer 的 9876

RocketMQ Dashboard

Dashboard 用于查看集群、Topic、Consumer、消息等信息。启动时需要指定 NameServer:

docker run -d \
  --name rocketmq-dashboard \
  -p 8080:8080 \
  -e "JAVA_OPTS=-Drocketmq.namesrv.addr=172.16.0.4:9876;172.16.0.17:9876;172.16.0.14:9876" \
  apache/rocketmq-dashboard:latest

生产环境同样建议固定镜像版本,不要直接使用 latest。

验证集群状态

查看集群列表:

sh bin/mqadmin clusterList -n 172.16.0.4:9876

查看 Topic 路由:

sh bin/mqadmin topicRoute -n 172.16.0.4:9876 -t TestTopic

创建 Topic:

sh bin/mqadmin updateTopic \
  -n 172.16.0.4:9876 \
  -c RaftCluster \
  -t TestTopic

发送消息测试:

export NAMESRV_ADDR=172.16.0.4:9876
sh bin/tools.sh org.apache.rocketmq.example.quickstart.Producer

消费消息测试:

export NAMESRV_ADDR=172.16.0.4:9876
sh bin/tools.sh org.apache.rocketmq.example.quickstart.Consumer

验证 DLedger 自动选主

验证步骤:

  1. 通过 Dashboard 或 mqadmin clusterList 确认当前 Leader。
  2. 停止 Leader 所在 Broker。
  3. 观察剩余两个节点是否重新选主。
  4. 再次发送消息验证是否可用。
  5. 恢复原节点,观察是否以 Follower 角色加入。

注意:至少 3 节点才能在 1 个节点故障后保持多数派。如果同时故障 2 个节点,集群将无法正常选主。

常见问题排查

1. 控制台连接 172.17.x.x 失败

现象:

RemotingConnectException: connect to <172.17.x.x:10911> failed

原因:Broker 注册了 Docker bridge 内部 IP。

处理:

  • 使用 host 网络。
  • 显式配置 brokerIP1 为宿主机 IP。
  • 确认端口映射和防火墙。

2. Broker 注册不到 NameServer

检查:

  • namesrvAddr 是否正确。
  • NameServer 是否启动。
  • 9876 端口是否连通。
  • Broker 日志中是否有注册失败。

3. DLedger 无法选主

检查:

  • 是否至少 3 个节点。
  • dLegerGroup 是否一致。
  • dLegerSelfId 是否唯一。
  • dLegerPeers 中节点和端口是否一致。
  • 40911 等 DLedger 通信端口是否互通。
  • 各节点时间是否相差过大。

4. 发送消息失败

检查:

  • Topic 是否创建。
  • Topic 路由是否正常。
  • Broker 是否有 Leader。
  • 客户端能否访问 brokerIP1:10911。
  • Broker 磁盘是否满。
  • Broker JVM 内存是否不足。

5. Broker 启动后很快退出

检查:

  • JVM 内存参数是否超过机器规格。
  • 存储目录权限是否正确。
  • storePathRootDir 是否可写。
  • 配置文件是否存在语法错误。

原实践中也通过调整 runbroker.sh 中 JVM 参数降低内存占用:

调整 runbroker JVM 参数

生产环境建议

  • DLedger Group 至少 3 个节点。
  • 不建议 2 节点部署 DLedger。
  • Broker 存储目录必须持久化。
  • dLegerSelfId 不能重复。
  • brokerIP1 必须是客户端可访问地址。
  • NameServer 建议多节点部署。
  • 磁盘建议使用 SSD,并监控 commitlog 写入延迟。
  • 监控 Broker 存活、磁盘、堆内存、消息堆积、发送失败率。
  • 不要混淆 Broker 端口、NameServer 端口和 DLedger 端口。
  • 重要变更先在测试环境演练,包括 Leader 故障切换。

RocketMQ 5.x Controller 模式说明

如果你使用的是 RocketMQ 5.x,需要额外关注 Controller 模式。Controller 模式是 RocketMQ 5.x 官方文档中用于自动主从切换的重要方案,与 4.x DLedger 部署方式不同。

因此选型时建议:

  • 仍使用 RocketMQ 4.x:可以参考 DLedger 方案。
  • 新项目或 RocketMQ 5.x:优先阅读官方 Controller 自动主从切换文档。
  • 不要混用两套方案的配置项。

总结

RocketMQ DLedger 集群搭建的关键点不是“把 3 个 Broker 启动起来”,而是确保:

  1. DLedger 节点满足多数派。
  2. dLegerPeers、dLegerSelfId、dLegerGroup 配置正确。
  3. Broker 注册到 NameServer 的地址对客户端可达。
  4. Docker 部署时避免容器内 IP 泄露给客户端。
  5. 存储目录持久化,端口互通,JVM 参数合理。
  6. 必须通过停 Leader 的方式验证自动选主。

如果遇到控制台或客户端连接 172.17.x.x 失败,优先排查 Docker 网络和 brokerIP1。

参考资料

  • RocketMQ 官方文档:DLedger 集群搭建
  • RocketMQ 官方文档:自动主从切换 Controller
  • RocketMQ 官方文档:Docker 快速开始
  • RocketMQ Dashboard
指南
RocketMQ DLedger 高可用 消息队列 Raft Docker 集群搭建 故障排查
License:  CC BY 4.0
Share

Further Reading

Jun 27, 2026

Agent 架构设计原则:Router、Runtime 与 Business Script 的职责划分

本文整理一套适合 Router Agent + Skill + Runtime 架构的设计原则:Agent 只负责业务决策,Runtime 统一负责执行、恢复、Trace、Checkpoint 和 Evidence,Business Script 只做确定性业务执行。

Sep 9, 2024

Redis 核心概念、数据结构与高可用架构详解

系统梳理 Redis 的核心数据类型、底层结构、过期与淘汰、持久化、事务、主从复制、Sentinel、Cluster、缓存一致性和分布式锁等机制,适合作为 Redis 学习、面试复习和高可用架构设计参考。

Sep 5, 2024

B+树原理与 MySQL InnoDB 索引机制解析

本文从 B+ 树的多叉平衡结构、叶子节点链表、范围查询和磁盘 I/O 特性出发,解释数据库索引为什么常采用 B+ 树,并结合 MySQL InnoDB 的聚簇索引、二级索引、回表、覆盖索引和联合索引机制理解其实际应用。

OLDER

Spring Boot 优雅停机实践:Graceful Shutdown、Actuator 与 Kubernetes 发布场景

NEWER

Maven 构建产物添加时间戳:maven.build.timestamp、build-helper 与可复现构建说明

Recently Updated

  • Agent 架构设计原则:Router、Runtime 与 Business Script 的职责划分
  • RocketMQ 架构设计与应用最佳实践:高可用消息队列核心解析
  • Redis 核心概念、数据结构与高可用架构详解
  • B+树原理与 MySQL InnoDB 索引机制解析
  • MySQL AUTO_INCREMENT 插入 0 变成自增值的原因与解决方案

Trending Tags

RocketMQ Windows Feign Docker Zipkin SonarQube OkHttp HttpClient API 性能优化

Contents

©2026 Ryan's Blog. Some rights reserved. · 粤ICP备2022031588号