MQ 部署运维
本文范围
MQ 不是把程序跑起来就结束了。
真正到生产现场,最容易出问题的地方往往不是“会不会发消息”,而是消费者突然不消费了、磁盘被消息打满了、Topic 随便创建没人管、权限还是默认账号、Broker 看起来活着但业务一直超时。
所以这里不展开最终一致性、事务消息业务设计、顺序消息业务建模那些架构话题,只讲运维落地:怎么安装、怎么组集群、怎么管权限、怎么看监控、怎么处理积压、磁盘满了怎么办、Broker 异常怎么恢复,以及 RabbitMQ、RocketMQ、Kafka 到底该怎么选。
先把三类 MQ 的定位说清楚:
| 组件 | 更适合的场景 | 运维最先盯什么 |
|---|---|---|
| RabbitMQ | 业务队列、任务分发、AMQP、路由规则比较灵活的系统 | vhost、Exchange、Queue、消费者、内存水位、磁盘水位 |
| RocketMQ | Java 业务消息、削峰填谷、订单链路、延迟消息、事务消息能力 | NameServer、Broker、Topic、消费进度、CommitLog、磁盘 |
| Kafka | 日志流、事件流、数据管道、可回放消费、高吞吐写入 | KRaft、Broker、Topic/Partition、副本、ISR、consumer lag、保留策略 |
这里要注意:MQ 不是无限缓冲池。消息能不能扛住,最后看的是磁盘、内存、网络、Broker 写入能力和消费者速度。消费者慢了,MQ 只是先帮你顶住一阵子,不会把下游问题自动解决掉。
前置条件
开始之前先准备这些基础条件,尤其是内网和离线现场,不要把下载包这件事留到上线窗口里:
- Linux 服务器或容器运行环境:生产 Broker 数据目录不要放系统盘。
- 运行依赖:RabbitMQ 需要匹配的 Erlang/OTP,RocketMQ 和 Kafka 需要 JDK,版本必须和目标组件文档对齐。
- 网络端口:RabbitMQ
5672/15672/25672,RocketMQ9876/10911,Kafka9092/9093这类端口要按客户端、Broker、控制面分别放行。 - 内网制品库:MQ 二进制包、容器镜像、Exporter、Dashboard、校验文件、启动脚本和配置模板都要可追溯。
- 监控入口:没有 consumer lag、队列积压、磁盘水位、Broker 存活和权限变更记录,不建议接生产业务。
1. 部署前先把边界定住
很多团队装 MQ 一上来就问“用哪个版本”,其实应该先问下面几个问题。
| 问题 | 为什么要问 |
|---|---|
| 消息是业务命令,还是日志事件流 | RabbitMQ/RocketMQ 更像业务消息系统,Kafka 更像可持久化事件日志 |
| 是否允许长时间积压 | RabbitMQ 不建议把大批量消息长期堆在单队列,Kafka/RocketMQ 更能承受大积压但也要算磁盘 |
| 消费失败后怎么处理 | 直接重试、死信队列、延迟重试、人工补偿,运维动作完全不一样 |
| Topic/Queue 谁来创建 | 生产不能随便自动创建,否则名字写错也可能变成线上对象 |
| 数据目录放哪里 | MQ 的命根子在数据目录,不能写到系统盘或临时目录 |
| 监控谁负责 | 没有 lag、磁盘、水位和 Broker 状态告警,故障通常发现得太晚 |
一般建议这样定:
| 环境 | 建议 |
|---|---|
| 本地验证 | 可以用容器或单机二进制包,只验证最小生产消费链路 |
| 测试环境 | 固定数据目录、固定日志目录、固定账号权限,尽量模拟生产参数 |
| 生产环境 | 至少 3 节点控制面,Broker 使用独立数据盘,监控告警先上线,再接业务 |
端口也要先列出来,不要等安全组、iptables、机房防火墙都卡住了再查。
| 组件 | 常见端口 | 作用 |
|---|---|---|
| RabbitMQ | 5672 | AMQP 客户端访问 |
| RabbitMQ | 15672 | Management 管理台 |
| RabbitMQ | 4369、25672 | Erlang 节点发现和集群通信 |
| RocketMQ NameServer | 9876 | 路由发现 |
| RocketMQ Broker | 10911、10909、10912 | Broker 对外访问、快速失败、HA 通信 |
| RocketMQ Proxy | 8080、8081 | 5.x Proxy 接入,按实际部署确认 |
| Kafka Broker | 9092 | 客户端访问 |
| Kafka Controller | 9093 | KRaft Controller 通信,示例端口 |
验证端口可以直接用:
ss -lntp | grep -E '5672|15672|9876|10911|9092|9093'如果没有输出,一般就是进程没有起来、端口配置不对,或者服务只监听在 127.0.0.1。如果有输出但远程连不上,再去查安全组、防火墙和路由。
三类 MQ 不要只按“都是消息队列”来部署。下面这张图适合在设计评审和上线检查时使用:先确认消息入口、存储单元和消费进度分别落在哪里,再决定监控指标、扩容动作和故障恢复方案。
这张图的核心不是选型,而是排障入口:RabbitMQ 先看 Queue 和 ACK,RocketMQ 先看 NameServer 路由、Broker 和消费组进度,Kafka 先看 Partition、ISR、Consumer Group LAG 和 log dir。上线前如果监控只覆盖了进程存活,没有覆盖这些对象,就不要急着接业务流量。
2. 中国大陆、内网和离线部署
MQ 部署不要默认外网一直顺畅。生产环境经常是服务器不能出网,Docker 镜像拉不动,GitHub 打不开,Apache 镜像站慢,最后上线窗口全耗在下载包上。
所以部署前一般需要准备三类东西:
- MQ 本体包,比如 RabbitMQ、RocketMQ、Kafka。
- 运行依赖,比如 JDK、Erlang、OpenSSL、socat、glibc、systemd。
- 周边组件,比如 Dashboard、Exporter、JMX Exporter、Prometheus 采集配置。
2.1 下载包怎么准备
优先从官方入口拿版本,再同步到企业制品库。不要在生产机器上临时 wget 一个来路不明的包。
下载后先做校验:
sha512sum rabbitmq-server-*.rpm
sha512sum rocketmq-all-*-bin-release.zip
sha512sum kafka_*.tgz这个命令解决的是“包有没有被改过、传输有没有损坏”的问题。执行后会输出一串 hash 值,要和官方 sha512 文件或企业制品库记录对得上。
如果官方同时提供签名文件,还要做 GPG 校验:
gpg --verify rocketmq-all-*-bin-release.zip.asc rocketmq-all-*-bin-release.zip
gpg --verify kafka_*.tgz.asc kafka_*.tgz正常情况下会看到签名校验通过。如果提示 BAD signature,不要继续安装;如果提示缺少公钥,先导入官方 KEYS 或企业内部已经审核过的公钥。
内网制品库建议按这个结构放:
mq/
rabbitmq/
server/
erlang/
plugins/
rocketmq/
binary/
dashboard/
exporter/
kafka/
binary/
jmx-exporter/
docker-images/
rabbitmq/
rocketmq/
kafka/这样做的好处很直接:版本、依赖、镜像都能追踪,出了问题能知道到底是谁升级了什么。
2.2 Docker 镜像怎么进内网
联网机器先拉取镜像,再保存成 tar 包,最后导入内网 Harbor 或其他私有仓库。下面以当前可用版本举例,落地前再到官方页确认补丁版本。
docker pull rabbitmq:4-management
docker pull apache/rocketmq:5.5.0
docker pull apache/kafka:4.3.1
docker save rabbitmq:4-management -o rabbitmq-4-management.tar
docker save apache/rocketmq:5.5.0 -o rocketmq-5.5.0.tar
docker save apache/kafka:4.3.1 -o kafka-4.3.1.tar
sha256sum *.tar > image.sha256这一步解决的是“内网机器不能直接拉镜像”的问题。sha256sum 是为了保证中间拷贝没有损坏。
内网机器执行:
sha256sum -c image.sha256
docker load -i rabbitmq-4-management.tar
docker load -i rocketmq-5.5.0.tar
docker load -i kafka-4.3.1.tar
docker images | grep -E 'rabbitmq|rocketmq|kafka'如果 sha256sum -c 失败,先重新传包,不要强行 docker load。如果 docker images 看不到镜像,多半是导入失败或者镜像名字不是你以为的那个。
生产环境建议再打上企业私有仓库标签:
docker tag rabbitmq:4-management registry.internal/mq/rabbitmq:4-management
docker tag apache/rocketmq:5.5.0 registry.internal/mq/rocketmq:5.5.0
docker tag apache/kafka:4.3.1 registry.internal/mq/kafka:4.3.1
docker push registry.internal/mq/rabbitmq:4-management
docker push registry.internal/mq/rocketmq:5.5.0
docker push registry.internal/mq/kafka:4.3.1这里要注意:业务部署脚本里尽量写私有仓库地址,不要把外部镜像仓库当成生产依赖。
2.3 离线部署验收
包导入成功不等于 MQ 能用。每次部署完至少跑下面几组命令。
查看进程:
jps
ps -ef | grep -E 'rabbit|rocketmq|kafka' | grep -v grep应该能看到对应服务进程。RocketMQ 和 Kafka 是 Java 进程,jps 一般能看到主类;RabbitMQ 主要看系统服务和 Erlang 进程。
查看端口:
ss -lntp | grep -E '5672|15672|9876|10911|9092|9093'应该看到端口处于 LISTEN。如果服务已启动但端口没有监听,优先看配置文件里的 listener 地址。
查看磁盘:
df -h
du -sh /data/* 2>/dev/null这里要看两个东西:数据盘是不是挂上了,MQ 数据目录是不是写到了预期目录。如果发现数据写到 / 根分区,马上停下来改。
最后做最小生产消费:
# RabbitMQ 用 rabbitmqadmin 或管理台发布一条消息再消费
# RocketMQ 用 tools.sh Producer/Consumer 或 mqadmin 验证
# Kafka 用 console producer/consumer 验证只有“能发、能收、能看到指标”,才算部署验收通过。
3. RabbitMQ 部署与管理
RabbitMQ 适合业务队列和路由比较灵活的场景。它的运维对象不是只有 Queue,还包括 Erlang cookie、vhost、Exchange、Binding、用户权限、队列类型和水位报警。
3.1 单机先跑起来
本地验证可以用容器,先把管理台和 AMQP 端口打开:
docker run -d \
--name rabbitmq \
-p 5672:5672 \
-p 15672:15672 \
-e RABBITMQ_DEFAULT_USER=admin \
-e RABBITMQ_DEFAULT_PASS='ChangeMe_123' \
rabbitmq:4-management这个命令做了几件事:
5672给应用连接。15672给管理台访问。RABBITMQ_DEFAULT_USER和RABBITMQ_DEFAULT_PASS创建初始管理员。
启动后先看日志:
docker logs -f rabbitmq正常情况下会看到 RabbitMQ 启动完成,并且 management 插件可用。然后访问:
http://服务器IP:15672/登录后应该能看到 Overview、Connections、Channels、Queues 等页面。如果打不开,先查容器是否运行:
docker ps | grep rabbitmq
ss -lntp | grep 15672如果容器在跑但端口没通,通常是端口映射、主机防火墙或安全组问题。
Linux 包安装时,按官方当前文档配置 Erlang 和 RabbitMQ 软件源。不要复制很老的 erlang-18、rabbitmq-server-3.6 之类命令,新系统会遇到依赖不兼容。
安装后常用命令如下:
systemctl enable rabbitmq-server
systemctl start rabbitmq-server
systemctl status rabbitmq-server
rabbitmq-plugins enable rabbitmq_management
rabbitmq-diagnostics status
rabbitmq-diagnostics listenerssystemctl status 看服务是否活着,rabbitmq-diagnostics status 看 RabbitMQ 自身状态,listeners 看端口是否监听。
配置文件一般在这些位置:
/etc/rabbitmq/rabbitmq.conf
/etc/rabbitmq/enabled_plugins
/var/lib/rabbitmq/
/var/log/rabbitmq/生产配置可以先从这几个参数开始:
listeners.tcp.default = 5672
management.tcp.port = 15672
vm_memory_high_watermark.relative = 0.4
disk_free_limit.absolute = 50GB
log.file.level = info这里要注意,disk_free_limit.absolute 不是装饰参数。RabbitMQ 发现磁盘可用空间低于这个值时,会触发磁盘报警并阻塞发布,防止把机器彻底写死。
改完配置后重启并验证:
systemctl restart rabbitmq-server
rabbitmq-diagnostics environment
rabbitmq-diagnostics alarms如果配置写错,服务可能起不来,直接看:
journalctl -u rabbitmq-server -n 200 --no-pager
tail -n 200 /var/log/rabbitmq/*.log3.2 用户、vhost 和权限
生产不要使用默认 guest/guest。guest 默认也只适合本机访问,不适合作为业务账号。
先建一个业务 vhost:
rabbitmqctl add_vhost /prod
rabbitmqctl list_vhosts/prod 就像一个逻辑隔离空间,生产、预发、测试不要混用一个 vhost。
再建一个管理账号,后面用它做对象验证:
rabbitmqctl add_user mq_admin 'ChangeMe_Admin_123'
rabbitmqctl set_user_tags mq_admin administrator
rabbitmqctl set_permissions -p /prod mq_admin ".*" ".*" ".*"再建业务账号:
rabbitmqctl add_user app_user 'ChangeMe_123'
rabbitmqctl set_permissions -p /prod app_user ".*" ".*" ".*"
rabbitmqctl list_permissions -p /prodset_permissions 后面三个正则分别是 configure、write、read。上面为了演示给了全权限,生产上应该按 Exchange、Queue 命名规则收窄。
建一个只读运维账号:
rabbitmqctl add_user ops_user 'ChangeMe_456'
rabbitmqctl set_user_tags ops_user monitoring
rabbitmqctl set_permissions -p /prod ops_user "" "" ".*"
rabbitmqctl list_usersmonitoring 标签能看监控信息,但不要让所有人都有 administrator。权限一旦乱了,排查消息丢失、误删队列会非常痛苦。
常见账号建议:
| 用户类型 | 标签 | 权限建议 |
|---|---|---|
| 应用账号 | 无管理标签 | 只给业务 vhost 下必要读写权限 |
| 运维只读账号 | monitoring | 可看队列、连接、节点,不允许改策略 |
| 管理员账号 | administrator | 少数人持有,用于用户、策略、插件治理 |
3.3 Exchange、Queue 和最小验证
RabbitMQ 的链路可以这样理解:
Producer -> Exchange -> Binding -> Queue -> Consumer生产者一般不是直接把消息扔进 Queue,而是发到 Exchange。Exchange 再根据 Binding 和 routing key 把消息路由到 Queue。
先安装或准备 rabbitmqadmin,然后创建一个 direct exchange:
rabbitmqadmin -u mq_admin -p ChangeMe_Admin_123 -V /prod \
declare exchange name=order.exchange type=direct durable=true这个命令创建的是持久化 Exchange。执行成功后可以在管理台的 Exchanges 页面看到 order.exchange。
创建队列:
rabbitmqadmin -u mq_admin -p ChangeMe_Admin_123 -V /prod \
declare queue name=order.created durable=true新业务如果要求队列高可用,优先评估 quorum queue,不要继续照旧资料配置 classic mirrored queue。
quorum queue 示例:
rabbitmqadmin -u mq_admin -p ChangeMe_Admin_123 -V /prod \
declare queue name=order.created.q durable=true \
arguments='{"x-queue-type":"quorum"}'绑定路由:
rabbitmqadmin -u mq_admin -p ChangeMe_Admin_123 -V /prod \
declare binding source=order.exchange destination=order.created routing_key=order.created发一条消息:
rabbitmqadmin -u mq_admin -p ChangeMe_Admin_123 -V /prod \
publish exchange=order.exchange routing_key=order.created payload='{"orderId":1001}'消费一条消息:
rabbitmqadmin -u mq_admin -p ChangeMe_Admin_123 -V /prod \
get queue=order.created ackmode=ack_requeue_false如果能看到 {"orderId":1001},说明 Exchange、Binding、Queue 链路没问题。
如果发成功但消费不到,一般按这个顺序查:
rabbitmqctl list_exchanges -p /prod name type durable
rabbitmqctl list_queues -p /prod name messages_ready consumers
rabbitmqctl list_bindings -p /prod重点看 routing key 是否写错、Exchange 和 Queue 是否在同一个 vhost、应用账号是否有写入或读取权限。
3.4 RabbitMQ 集群
RabbitMQ 集群里最容易踩的是 Erlang cookie 和主机名。
先在每个节点设置稳定主机名:
hostnamectl set-hostname rabbit-1rabbit-1、rabbit-2、rabbit-3 要能互相解析,可以用 DNS,也可以在小环境里维护 /etc/hosts。不要今天用 IP,明天改 hostname。
节点 1 启动后查看 cookie:
systemctl start rabbitmq-server
cat /var/lib/rabbitmq/.erlang.cookie节点 2、3 同步这个 cookie:
systemctl stop rabbitmq-server
scp rabbit-1:/var/lib/rabbitmq/.erlang.cookie /var/lib/rabbitmq/.erlang.cookie
chown rabbitmq:rabbitmq /var/lib/rabbitmq/.erlang.cookie
chmod 400 /var/lib/rabbitmq/.erlang.cookie
systemctl start rabbitmq-server这里要注意,cookie 内容必须一致,权限一般要是 400。权限不对时,经常会看到节点互相认证失败。
在节点 2、3 加入集群:
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster rabbit@rabbit-1
rabbitmqctl start_app
rabbitmqctl cluster_statuscluster_status 里应该能看到多个 running nodes。如果只看到自己,说明没有真正加入成功。
生产建议:
| 项 | 建议 |
|---|---|
| 节点数 | 3 个起步,避免单点 |
| 队列类型 | 新业务优先评估 quorum queue |
| 入口 | 应用配置多个 RabbitMQ 地址,或用四层负载均衡代理 5672 |
| 管理台 | 只放内网或 VPN,不要暴露公网 |
| 数据目录 | 独立磁盘,定期看水位 |
HAProxy 四层代理示例:
listen rabbitmq_amqp
bind 0.0.0.0:5672
mode tcp
option tcplog
balance roundrobin
timeout connect 5s
timeout client 60s
timeout server 60s
server rabbit1 rabbit-1:5672 check inter 5s rise 2 fall 3
server rabbit2 rabbit-2:5672 check inter 5s rise 2 fall 3
server rabbit3 rabbit-3:5672 check inter 5s rise 2 fall 3配置完成后在应用机器上验证:
nc -vz rabbit-lb 5672能连通只说明网络通了,还要用业务账号实际发收消息。
3.5 RabbitMQ 监控
RabbitMQ 排障不要只看管理台。命令行更快,尤其是线上访问管理台不方便的时候。
常用命令:
rabbitmq-diagnostics status
rabbitmq-diagnostics alarms
rabbitmq-diagnostics memory_breakdown
rabbitmqctl list_connections name user peer_host state channels
rabbitmqctl list_channels connection number consumer_count messages_unacknowledged
rabbitmqctl list_queues -p /prod name durable type messages_ready messages_unacknowledged consumers memory state怎么看结果:
| 指标 | 怎么理解 |
|---|---|
messages_ready | 队列里等着消费的消息,持续增长说明消费者处理不过来 |
messages_unacknowledged | 已经投递给消费者但还没 ACK,持续很高说明消费者卡住或 prefetch 过大 |
consumers | 消费者数量,业务队列为 0 要马上查应用 |
| memory alarm | 内存水位报警,发布可能被阻塞 |
| disk alarm | 磁盘水位报警,发布会受影响 |
| connection/channel | 连接和信道数量,异常增长可能是连接泄漏或短连接风暴 |
开启 Prometheus 插件:
rabbitmq-plugins enable rabbitmq_prometheus
curl http://127.0.0.1:15692/metrics | head如果 curl 能看到指标文本,就可以接 Prometheus。生产上至少要告警:磁盘水位、内存水位、队列积压、消费者数量、连接数、节点存活。
3.6 RabbitMQ 积压怎么查
业务说“消息没消费”,先别急着重启 RabbitMQ。先看队列。
rabbitmqctl list_queues -p /prod name messages_ready messages_unacknowledged consumers memory常见判断:
| 现象 | 一般原因 | 处理思路 |
|---|---|---|
messages_ready 持续增长,consumers=0 | 消费者没启动、连错 vhost、权限不对 | 恢复消费者,检查应用配置和 RabbitMQ 权限 |
messages_unacknowledged 很高 | 消费者拿到消息但没 ACK | 查消费线程、下游接口、数据库慢查询、prefetch |
| 队列内存很高 | 消息体大、队列堆积、惰性策略不合理 | 限流生产者,拆大消息,扩容消费者 |
| disk alarm | 数据盘水位太高 | 扩容、迁移、清理无用队列,不要手删数据文件 |
| 单队列特别大 | 热点 routing key 或单消费者模型 | 拆队列、拆路由、增加消费者并发 |
再看连接:
rabbitmqctl list_connections name user peer_host state channels
rabbitmqctl list_channels connection number consumer_count messages_unacknowledged如果一个连接下面堆了很多 unacked 消息,通常就是某个消费者实例卡住了。这个时候重启对应消费者,比重启 RabbitMQ 更合理。
最后看日志:
journalctl -u rabbitmq-server -n 200 --no-pager
tail -n 200 /var/log/rabbitmq/*.log这里要注意:RabbitMQ 的 ACK 是业务处理完成后的确认,不是消息投递出去就算完成。如果消费者拿到消息后一直不 ACK,MQ 会认为消息还在处理中。
生产建议:
prefetchCount不要设置成无限大。- 业务处理成功后再 ACK。
- 异常消息进入死信队列,不要无限 requeue。
- 大消息不要直接塞 MQ,建议存对象存储,只传引用。
- 消费者下游故障时要限流,不要让 MQ 替下游无限兜底。
4. RocketMQ 部署与 NameServer/Broker
RocketMQ 要先分清 NameServer 和 Broker。
Producer/Consumer -> NameServer 获取路由 -> Broker 写入和读取消息NameServer 负责路由发现,不保存消息。Broker 才保存 CommitLog、ConsumeQueue、IndexFile。磁盘满、积压、恢复,核心基本都在 Broker。
4.1 单机快速启动
先确认 JDK:
java -version如果连 Java 都没有,RocketMQ 进程不会正常启动。生产环境要统一 JDK 基线,不要一台机器一个版本。
解压 RocketMQ:
unzip rocketmq-all-5.5.0-bin-release.zip -d /opt
cd /opt/rocketmq-all-5.5.0-bin-release
mkdir -p logs启动 NameServer:
nohup sh bin/mqnamesrv > logs/namesrv.out 2>&1 &
tail -f logs/namesrv.out看到类似 NameServer 启动成功的信息后,再启动 Broker:
nohup sh bin/mqbroker -n 127.0.0.1:9876 > logs/broker.out 2>&1 &
tail -f logs/broker.out验证生产和消费:
export NAMESRV_ADDR=127.0.0.1:9876
sh bin/tools.sh org.apache.rocketmq.example.quickstart.Producer
sh bin/tools.sh org.apache.rocketmq.example.quickstart.ConsumerProducer 正常会连续发送测试消息,Consumer 正常会打印收到的消息。
如果进程刚启动就退出,一般看三个地方:
tail -n 200 logs/namesrv.out
tail -n 200 logs/broker.out
grep -n "JAVA_OPT" -n bin/runserver.sh bin/runbroker.sh小内存虚拟机经常是 JVM 参数太大导致启动失败。测试环境可以调小,生产环境要按容量规划给足内存。
4.2 Broker 数据目录
生产不要让 Broker 数据写到默认临时目录。先准备独立数据盘:
mkdir -p /data/rocketmq/store/{commitlog,consumequeue,index}
mkdir -p /data/rocketmq/logs
chown -R rocketmq:rocketmq /data/rocketmq这几个目录分别保存消息本体、消费队列索引、查询索引和日志。CommitLog 是大头,磁盘规划主要看它。
Broker 配置示例:
brokerClusterName=rocketmq-cluster
brokerName=broker-a
brokerId=0
namesrvAddr=ns1:9876;ns2:9876;ns3:9876
listenPort=10911
autoCreateTopicEnable=false
autoCreateSubscriptionGroup=false
storePathRootDir=/data/rocketmq/store
storePathCommitLog=/data/rocketmq/store/commitlog
storePathConsumeQueue=/data/rocketmq/store/consumequeue
storePathIndex=/data/rocketmq/store/index
storeCheckpoint=/data/rocketmq/store/checkpoint
abortFile=/data/rocketmq/store/abort
deleteWhen=04
fileReservedTime=72
diskMaxUsedSpaceRatio=85
brokerRole=ASYNC_MASTER
flushDiskType=ASYNC_FLUSH
sendMessageThreadPoolNums=16
aclEnable=true
traceTopicEnable=true几个关键点:
| 配置 | 怎么理解 |
|---|---|
brokerName | 同一组主从要相同 |
brokerId | 0 是 Master,大于 0 是 Slave |
autoCreateTopicEnable | 生产建议关闭,Topic 走变更流程 |
storePath* | 指向独立数据盘,禁止写系统盘 |
diskMaxUsedSpaceRatio | 磁盘水位阈值,要提前告警 |
flushDiskType | 同步刷盘更稳,异步刷盘吞吐更好 |
brokerRole | 根据可靠性要求选择同步/异步主从 |
启动指定配置:
nohup sh bin/mqbroker \
-n ns1:9876\;ns2:9876\;ns3:9876 \
-c conf/broker-a.properties \
> logs/broker-a.out 2>&1 &分号在 shell 里要转义,或者直接把 NameServer 地址写进配置文件。启动后验证:
sh bin/mqadmin clusterList -n ns1:9876
sh bin/mqadmin brokerStatus -n ns1:9876 -b broker-a:10911clusterList 能看到 Broker 才说明路由注册成功。如果 NameServer 正常但 clusterList 看不到 Broker,优先查 Broker 日志和 namesrvAddr。
4.3 RocketMQ 集群
常见部署形态有三种:
| 模式 | 说明 | 使用建议 |
|---|---|---|
2m-noslave | 两主无从 | 有单点数据风险,只适合测试或低可靠场景 |
2m-2s-async | 两主两从,异步复制 | 吞吐较好,极端故障可能丢少量消息 |
2m-2s-sync | 两主两从,同步复制 | 可靠性更好,吞吐下降 |
如果选择 DLedger,要按官方配置模板准备 3 节点复制组。示例参数如下:
enableDLegerCommitLog=true
dLegerGroup=broker-a
dLegerPeers=n0-broker-a:40911;n1-broker-a:40911;n2-broker-a:40911
dLegerSelfId=n0这里要注意,DLedger 的每个节点 dLegerSelfId 不能一样,dLegerPeers 要能互相解析和连通。
检查集群:
sh bin/mqadmin clusterList -n ns1:9876
sh bin/mqadmin topicList -n ns1:9876生产创建 Topic:
sh bin/mqadmin updateTopic \
-n ns1:9876 \
-c rocketmq-cluster \
-t order.created \
-r 8 \
-w 8-r 是读队列数,-w 是写队列数。队列数不是越大越好,太小会限制并发,太大会增加 Broker 和客户端管理成本。一般先按消费者并发、峰值 TPS、消息大小评估。
查看 Topic 路由:
sh bin/mqadmin topicRoute -n ns1:9876 -t order.created应该能看到 Topic 分布在哪些 Broker 上。如果没有路由,说明 Topic 没创建成功,或者创建到了另一个集群。
4.4 RocketMQ 权限
生产开启 ACL:
aclEnable=true常见 ACL 文件示例:
globalWhiteRemoteAddresses:
- 10.0.0.*
accounts:
- accessKey: order-app
secretKey: ChangeMe_123
whiteRemoteAddress:
admin: false
defaultTopicPerm: DENY
defaultGroupPerm: DENY
topicPerms:
- order.created=PUB|SUB
groupPerms:
- order-consumer=SUB改完后重启 Broker 或按当前版本支持的方式热加载,再用业务客户端实际发收验证。
权限问题常见现象是:客户端能连上 NameServer,但发送或订阅时报权限拒绝。这个时候不要只查网络,要同时查 accessKey、secretKey、Topic 权限、Group 权限和客户端 IP 白名单。
4.5 RocketMQ 监控
先用命令看基础状态:
sh bin/mqadmin clusterList -n ns1:9876
sh bin/mqadmin brokerStatus -n ns1:9876 -b broker-a:10911
sh bin/mqadmin consumerProgress -n ns1:9876 -g order-consumer
sh bin/mqadmin consumerStatus -n ns1:9876 -g order-consumer怎么看:
| 指标/命令 | 关注点 |
|---|---|
clusterList | Broker 是否在线,主从是否正常 |
brokerStatus | TPS、延迟、磁盘相关状态 |
consumerProgress | 消费积压是否增长 |
consumerStatus | 消费者实例是否在线,分配是否正常 |
系统层也要看:
df -h
iostat -x 1
free -h
ulimit -n
cat /proc/sys/vm/max_map_countRocketMQ 和 Kafka 都大量依赖文件和 mmap。文件句柄太低、磁盘 IO 延迟高、max_map_count 太小,都可能表现成 Broker 抖动或发送超时。
生产建议把这些指标接入 Prometheus/Grafana 或等价平台:
- Broker 存活。
- 生产 TPS 和消费 TPS。
- 消费积压。
- 磁盘使用率。
- 发送耗时。
- Broker 主从复制状态。
- JVM GC 和堆内存。
4.6 RocketMQ 消费积压处理
先看消费进度:
sh bin/mqadmin consumerProgress -n ns1:9876 -g order-consumer如果 lag 一直涨,说明生产速度大于消费速度,或者消费者根本没正常消费。
再看消费者状态:
sh bin/mqadmin consumerStatus -n ns1:9876 -g order-consumer常见原因:
| 现象 | 一般原因 | 处理方式 |
|---|---|---|
| 消费者实例为 0 | 应用没启动、Group 写错、权限拒绝 | 恢复应用,检查 group 和 ACL |
| lag 增长但消费者在线 | 下游慢、线程池满、单条消息处理慢 | 扩容消费者,优化下游,临时限流生产 |
| 某几个队列积压特别高 | 队列分配不均或热点 key | 调整队列数、消费者并发和 key 设计 |
| 重试消息很多 | 业务异常一直失败 | 查异常栈,进入死信或人工处理 |
如果只是消费者数量不够,可以扩容消费者实例。扩容后再看:
sh bin/mqadmin consumerProgress -n ns1:9876 -g order-consumer正常情况 lag 应该开始下降。如果扩容后不降,多半瓶颈在数据库、远程接口、锁竞争或单消息处理逻辑,不在 MQ。
这里要注意:不要一看到积压就盲目扩 Broker。消费慢通常先扩消费者,Broker 扩容解决的是存储、写入和队列分布问题。
4.7 RocketMQ 磁盘满
RocketMQ 磁盘满常见表现:
- 生产者发送超时或失败。
- Broker 日志出现磁盘水位、拒绝写入相关信息。
- 消费进度不动。
df -h看到数据盘接近 100%。
先查磁盘:
df -h
du -sh /data/rocketmq/store/*
tail -n 200 logs/broker-a.out再查 Broker 配置:
grep -E 'storePath|fileReservedTime|diskMaxUsedSpaceRatio|deleteWhen' conf/broker-a.properties处理顺序一般是:
- 先限流生产者,防止继续写爆。
- 判断是否有无用 Topic 或测试 Topic 可以按流程下线。
- 扩容数据盘或迁移到更大的挂载点。
- 必要时临时缩短保留时间,但要业务确认消息是否允许过期删除。
- 恢复后继续观察
consumerProgress,确认积压下降。
不要在 Broker 运行时随手删除 CommitLog 文件。看起来腾出了空间,实际可能把索引和消息链路弄坏。必须做清理时,先停机、备份、确认版本和恢复方案。
5. Kafka 部署与 KRaft/ZooKeeper 边界
Kafka 的核心对象是 Topic、Partition、Replica 和 Consumer Group。
Producer -> Topic Partition -> Broker Log -> Consumer Group OffsetKafka 新集群优先使用 KRaft。ZooKeeper 模式主要是历史集群维护和迁移问题,不建议新部署再走 ZooKeeper。
这里要注意:Kafka 4.x 已经是 KRaft 时代,老文章里大量 ZooKeeper 启动命令不能直接套到新集群。
5.1 KRaft 单机验证
先解压:
tar -xzf kafka_2.13-4.3.1.tgz -C /opt
cd /opt/kafka_2.13-4.3.1生成集群 ID:
KAFKA_CLUSTER_ID="$(bin/kafka-storage.sh random-uuid)"
echo "$KAFKA_CLUSTER_ID"格式化存储目录:
bin/kafka-storage.sh format --standalone -t "$KAFKA_CLUSTER_ID" -c config/server.properties这个命令会把 KRaft 元数据写入本机数据目录。格式化之后不要随便换 cluster id,否则节点会认为自己属于另一个集群。
启动 Kafka:
bin/kafka-server-start.sh -daemon config/server.properties
tail -f logs/server.log验证 Topic:
bin/kafka-topics.sh --bootstrap-server 127.0.0.1:9092 --create \
--topic order-created \
--partitions 3 \
--replication-factor 1
bin/kafka-topics.sh --bootstrap-server 127.0.0.1:9092 --describe --topic order-created能看到 3 个 Partition,说明 Topic 创建成功。
发送消息:
bin/kafka-console-producer.sh --bootstrap-server 127.0.0.1:9092 --topic order-created输入一行:
{"orderId":1001}另开一个窗口消费:
bin/kafka-console-consumer.sh --bootstrap-server 127.0.0.1:9092 \
--topic order-created \
--from-beginning应该能看到刚才输入的 JSON。如果看不到,先查 Topic 名字、Broker 地址和日志。
5.2 KRaft 集群配置
生产一般不要把数据写到默认目录,先准备数据盘:
mkdir -p /data/kafka/logs
chown -R kafka:kafka /data/kafka3 节点 KRaft 示例配置:
process.roles=broker,controller
node.id=1
controller.quorum.voters=1@kafka-1:9093,2@kafka-2:9093,3@kafka-3:9093
listeners=PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093
advertised.listeners=PLAINTEXT://kafka-1:9092
controller.listener.names=CONTROLLER
listener.security.protocol.map=PLAINTEXT:PLAINTEXT,CONTROLLER:PLAINTEXT
inter.broker.listener.name=PLAINTEXT
log.dirs=/data/kafka/logs
num.partitions=6
default.replication.factor=3
min.insync.replicas=2
auto.create.topics.enable=false
log.retention.hours=72
log.segment.bytes=1073741824每台机器的 node.id 和 advertised.listeners 要改成自己的。controller.quorum.voters 三台保持一致。
生成一个集群 ID,然后三台都用同一个 ID 格式化:
KAFKA_CLUSTER_ID="$(bin/kafka-storage.sh random-uuid)"
echo "$KAFKA_CLUSTER_ID"
bin/kafka-storage.sh format -t "$KAFKA_CLUSTER_ID" -c config/server.properties启动后验证:
bin/kafka-metadata-quorum.sh --bootstrap-server kafka-1:9092 describe --status
bin/kafka-broker-api-versions.sh --bootstrap-server kafka-1:9092metadata-quorum 能看到 leader 和 voter,说明 KRaft 控制面工作正常。
这里要注意:advertised.listeners 是客户端真正拿到的地址。如果写成 localhost,本机测试能通,别的机器全部连不上。
5.3 ZooKeeper 老集群边界
如果你维护的是老 Kafka 集群,看到这样的配置就是 ZooKeeper 模式:
zookeeper.connect=zk1:2181,zk2:2181,zk3:2181/kafka老集群不要一拍脑袋直接改成 KRaft。迁移涉及元数据、版本、停机窗口、客户端兼容性和回滚方案,要按官方迁移文档和企业变更流程执行。
运维时至少要查:
echo ruok | nc zk1 2181
echo mntr | nc zk1 2181如果 ZooKeeper 异常,Kafka 旧集群可能出现 Topic 元数据变更失败、Controller 切换异常、Broker 注册异常。新集群则优先看 KRaft quorum。
5.4 Topic、Partition 和副本
生产创建 Topic:
bin/kafka-topics.sh --bootstrap-server kafka-1:9092 --create \
--topic order-created \
--partitions 12 \
--replication-factor 3 \
--config min.insync.replicas=2 \
--config retention.ms=259200000参数怎么理解:
partitions=12决定并发读写的基本上限。replication-factor=3表示每个分区 3 副本。min.insync.replicas=2表示至少 2 个同步副本才认为写入可靠。retention.ms=259200000表示保留 3 天。
查看 Topic:
bin/kafka-topics.sh --bootstrap-server kafka-1:9092 --describe --topic order-created应该看到每个 Partition 的 Leader、Replicas、Isr。这里重点看 Isr,如果 Isr 长期少于副本数,说明副本同步有问题。
生产者也要配合:
acks=all
retries=3
enable.idempotence=true
delivery.timeout.ms=120000如果 min.insync.replicas=2,但生产者 acks=1,可靠性就没有真正用起来。
5.5 Kafka 权限
生产不要裸奔 PLAINTEXT。内网环境至少要有网络隔离;更规范的做法是 SASL/SSL 或 mTLS。
开启 ACL 后,常用授权如下:
bin/kafka-acls.sh --bootstrap-server kafka-1:9092 \
--add \
--allow-principal User:order-app \
--operation Write \
--topic order-created
bin/kafka-acls.sh --bootstrap-server kafka-1:9092 \
--add \
--allow-principal User:order-app \
--operation Read \
--group order-service查看权限:
bin/kafka-acls.sh --bootstrap-server kafka-1:9092 --list常见报错:
| 报错 | 一般原因 |
|---|---|
TopicAuthorizationException | Topic 写入或读取权限缺失 |
GroupAuthorizationException | Consumer Group 权限缺失 |
| 认证失败 | 用户名、密码、JAAS、证书或监听器协议不一致 |
这里要注意,Kafka 权限是跟 principal、Topic、Group 等资源绑定的。只给 Topic Read 不给 Group Read,消费者照样会失败。
5.6 Kafka 监控
先用命令看基本状态:
bin/kafka-topics.sh --bootstrap-server kafka-1:9092 --describe
bin/kafka-consumer-groups.sh --bootstrap-server kafka-1:9092 --all-groups --describe
bin/kafka-log-dirs.sh --bootstrap-server kafka-1:9092 --describe消费组输出里最关键的是这几列:
CURRENT-OFFSET LOG-END-OFFSET LAGLOG-END-OFFSET - CURRENT-OFFSET = LAG。LAG 持续增长,就是消费追不上生产。
JMX 指标必须接入监控,至少看:
| 指标 | 为什么重要 |
|---|---|
| UnderReplicatedPartitions | 副本不同步,可靠性下降 |
| OfflinePartitionsCount | 分区不可用,业务会受影响 |
| ActiveControllerCount | 正常应该只有一个 Controller |
| RequestHandlerAvgIdlePercent | 请求线程是否快被打满 |
| BytesIn/BytesOut | 写入和读取吞吐 |
| consumer lag | 消费积压 |
| 磁盘使用率 | Kafka 最常见的硬故障之一 |
JMX Exporter 接入后,要做看板和告警,不要只靠人工巡检。
5.7 Kafka 积压怎么处理
先查消费者组:
bin/kafka-consumer-groups.sh --bootstrap-server kafka-1:9092 \
--describe \
--group order-service如果看到 LAG 持续增长,按下面顺序判断:
| 现象 | 一般原因 | 处理 |
|---|---|---|
| Consumer 数量为 0 | 应用没启动、认证失败、Group 写错 | 恢复消费者,查应用日志 |
| LAG 增长但消费者在线 | 下游慢、消费线程少、处理逻辑慢 | 扩容消费者,优化下游,临时限流 |
| 某个 Partition LAG 特别高 | key 热点或单分区顺序消费卡住 | 查热点 key,评估拆分 Topic 或 key |
| Rebalance 频繁 | 消费者超时、心跳异常、实例频繁发布 | 调整超时参数,稳定实例 |
| Offset 不动 | 消费者卡死或提交失败 | 查线程栈、异常日志和提交策略 |
扩容消费者时要知道一个边界:同一个 Consumer Group 内,一个 Partition 同一时间只能被一个消费者实例消费。消费者数量超过 Partition 数,不会继续提升这个 Topic 的并行度。
如果确实需要提升并行度,可以增加 Partition:
bin/kafka-topics.sh --bootstrap-server kafka-1:9092 \
--alter \
--topic order-created \
--partitions 24这里要注意:增加 Partition 可能改变 key 的分布,影响按 key 顺序消费的业务。运维上能改,不代表业务上一定能改。
5.8 Kafka 磁盘满
Kafka 磁盘满常见表现:
- 生产者发送超时。
- Broker 日志出现 no space、log dir failed。
- 副本同步异常。
- 某些 Partition 离线。
先查系统盘和数据盘:
df -h
du -sh /data/kafka/logs/*再查 Kafka 看到的日志目录:
bin/kafka-log-dirs.sh --bootstrap-server kafka-1:9092 --describe如果是某个 Topic 占用太多,可以临时缩短保留时间,但一定要业务确认:
bin/kafka-configs.sh --bootstrap-server kafka-1:9092 \
--alter \
--entity-type topics \
--entity-name order-created \
--add-config retention.ms=8640000086400000 是 1 天。改完后 Kafka 不会立刻把所有旧数据删光,它按日志段滚动和清理策略执行,所以还要继续观察磁盘。
恢复建议:
- 先限流生产者,避免继续写爆。
- 查哪个 Topic、哪个 Broker、哪个 log dir 占用最大。
- 能删的是过期数据,不能删的是业务数据。
- 长期方案是扩容磁盘、调整保留策略、做冷热分层或数据归档。
不要直接手删 Kafka log 目录里的分区文件。手删可能导致 Broker 启动失败或数据不可恢复。
6. Topic 和 Queue 怎么理解
三类 MQ 名字不一样,排障时要抓住“消息最终落在哪里,消费进度由谁维护”。
| 组件 | 生产入口 | 存储单元 | 消费进度 |
|---|---|---|---|
| RabbitMQ | Exchange | Queue | Broker 记录投递和 ACK 状态 |
| RocketMQ | Topic | MessageQueue/CommitLog | Broker 保存消费进度 |
| Kafka | Topic | Partition Log | Consumer Group Offset |
RabbitMQ 看 Queue,RocketMQ 看 Topic 下的队列和消费组,Kafka 看 Topic Partition 和 consumer lag。
一个简单的判断方法:
- RabbitMQ 消息不动,先看 Queue 里的
messages_ready和unacked。 - RocketMQ 消息不动,先看
consumerProgress。 - Kafka 消息不动,先看 Consumer Group 的 LAG。
不要把这三个产品强行按一个模型理解。RabbitMQ 的 Queue 不是 Kafka 的 Partition,Kafka 的 Topic 也不是 RocketMQ 的 Topic 完全等价。
积压排障可以按下面这条链路走。它适合放进故障手册里,值班同学先按图确认生产速率、Broker 磁盘和消费进度,再决定是恢复消费者、限流、扩容,还是把失败消息转入 DLQ 和补偿流程。
这里的生产约束要提前说清:消费者实例数超过 Kafka Partition 数不一定继续提速;RocketMQ 顺序消息不能随意拆队列并发;RabbitMQ 单队列热点要看 messages_ready、messages_unacknowledged、consumers 和 prefetch。积压恢复结束后,必须验证 lag 是否持续下降、Broker 磁盘是否回到安全水位、DLQ 或重试队列是否清空,以及补偿结果是否能被业务抽样确认。
7. 权限和安全基线
MQ 权限不能等出事再补。
生产至少做到:
- 禁止默认账号直接用于业务。
- 不同环境用不同 vhost、Topic、Group 或集群隔离。
- 管理台不暴露公网。
- 业务账号只给必要权限。
- 密码、accessKey、证书进入密钥管理系统。
- 权限变更有记录,能回滚。
快速检查:
# RabbitMQ
rabbitmqctl list_users
rabbitmqctl list_permissions -p /prod
# RocketMQ
grep -R "aclEnable" conf/
grep -R "accessKey" conf/
# Kafka
bin/kafka-acls.sh --bootstrap-server kafka-1:9092 --list如果检查结果里出现没人知道的管理员账号、全量通配权限、测试账号还在生产使用,就要马上收口。
8. 数据目录、日志和容量规划
MQ 的容量规划不是只看“每天多少条消息”,还要看消息大小、保留时间、副本数、峰值、重试和积压。
一个粗略公式:
磁盘需求 = 日消息量 * 平均消息大小 * 保留天数 * 副本数 * 预留系数预留系数一般不要低于 1.3,业务波动大的系统可以更高。
数据目录建议:
| 组件 | 数据目录 | 日志目录 |
|---|---|---|
| RabbitMQ | /var/lib/rabbitmq 或独立挂载目录 | /var/log/rabbitmq |
| RocketMQ | /data/rocketmq/store | /data/rocketmq/logs |
| Kafka | /data/kafka/logs | logs/ 或系统日志目录 |
查看占用:
df -h
du -sh /data/rocketmq/store/* 2>/dev/null
du -sh /data/kafka/logs/* 2>/dev/null
du -sh /var/lib/rabbitmq/* 2>/dev/null生产建议:
- 数据盘和系统盘分开。
- Broker 日志要轮转。
- 保留策略要按 Topic/业务级别配置,不要全局一刀切。
- 大消息要限制,必要时只传文件引用。
- 容量告警至少提前到 70%、80%、90% 三档。
9. 日常巡检
巡检不是为了截图,而是提前发现“快要炸”的地方。
RabbitMQ:
rabbitmq-diagnostics status
rabbitmq-diagnostics alarms
rabbitmqctl list_queues -p /prod name messages_ready messages_unacknowledged consumers memory
rabbitmqctl list_connections name user peer_host state channelsRocketMQ:
sh bin/mqadmin clusterList -n ns1:9876
sh bin/mqadmin consumerProgress -n ns1:9876 -g order-consumer
sh bin/mqadmin brokerStatus -n ns1:9876 -b broker-a:10911
df -hKafka:
bin/kafka-metadata-quorum.sh --bootstrap-server kafka-1:9092 describe --status
bin/kafka-topics.sh --bootstrap-server kafka-1:9092 --describe
bin/kafka-consumer-groups.sh --bootstrap-server kafka-1:9092 --all-groups --describe
bin/kafka-log-dirs.sh --bootstrap-server kafka-1:9092 --describe
df -h巡检结果重点看:
- 有没有节点离线。
- 有没有积压持续增长。
- 磁盘是否超过阈值。
- 副本是否不同步。
- 消费者数量是否异常。
- 日志里是否有连续错误。
10. 常见故障排查
10.1 生产者发送失败
先别猜代码问题,先看连通性。
nc -vz rabbit-1 5672
nc -vz ns1 9876
nc -vz kafka-1 9092能通再看权限和服务状态。
RabbitMQ:
rabbitmq-diagnostics alarms
rabbitmqctl list_permissions -p /prodRocketMQ:
sh bin/mqadmin clusterList -n ns1:9876
tail -n 200 logs/broker-a.outKafka:
bin/kafka-topics.sh --bootstrap-server kafka-1:9092 --describe --topic order-created
bin/kafka-acls.sh --bootstrap-server kafka-1:9092 --list常见原因:
- 端口不通。
- 账号没有写权限。
- Topic/Queue 不存在。
- 磁盘水位触发拒绝写。
- Broker 不在线或副本不足。
10.2 消费者不消费
先查消费者是否在线。
RabbitMQ:
rabbitmqctl list_queues -p /prod name consumers messages_ready messages_unacknowledgedRocketMQ:
sh bin/mqadmin consumerStatus -n ns1:9876 -g order-consumerKafka:
bin/kafka-consumer-groups.sh --bootstrap-server kafka-1:9092 --describe --group order-service如果消费者不在线,查应用启动、配置和认证。如果消费者在线但 lag 不降,查下游依赖、线程池、异常重试和单条消息耗时。
10.3 Broker 异常
Broker 异常先看三个东西:日志、磁盘、端口。
df -h
ss -lntp
journalctl -xe --no-pager | tail -n 100RabbitMQ:
journalctl -u rabbitmq-server -n 200 --no-pager
rabbitmq-diagnostics statusRocketMQ:
tail -n 300 logs/broker-a.out
sh bin/mqadmin brokerStatus -n ns1:9876 -b broker-a:10911Kafka:
tail -n 300 logs/server.log
bin/kafka-metadata-quorum.sh --bootstrap-server kafka-1:9092 describe --status如果是磁盘满,优先扩容和限流。如果是配置错误,回滚最近一次配置。如果是 JVM OOM,先保留日志和 heap dump,再分析消息量、批大小、连接数和内存参数。
10.4 集群扩容
扩容不是“加一台机器”就完了,还要让数据和流量真的过去。
RabbitMQ 扩容:
rabbitmqctl join_cluster rabbit@rabbit-1
rabbitmqctl cluster_status加入成功后,还要确认队列类型和副本策略。quorum queue 是否按预期分布,要通过管理台或命令继续检查。
RocketMQ 扩容:
nohup sh bin/mqbroker -n ns1:9876\;ns2:9876 -c conf/broker-c.properties > logs/broker-c.out 2>&1 &
sh bin/mqadmin clusterList -n ns1:9876Broker 上线后,新 Topic 可以分布到新 Broker;老 Topic 是否迁移,要按业务低峰和官方工具流程做。
Kafka 扩容:
bin/kafka-broker-api-versions.sh --bootstrap-server kafka-1:9092
bin/kafka-reassign-partitions.sh --bootstrap-server kafka-1:9092 --execute --reassignment-json-file reassignment.json
bin/kafka-reassign-partitions.sh --bootstrap-server kafka-1:9092 --verify --reassignment-json-file reassignment.jsonKafka 扩容后如果不做分区重分配,新 Broker 可能只是“在线”,并没有承接老 Topic 的数据和流量。
10.5 备份和恢复
RabbitMQ 可以备份定义:
rabbitmqctl export_definitions /backup/rabbitmq-definitions.json
rabbitmqctl import_definitions /backup/rabbitmq-definitions.json这里备份的是用户、vhost、Exchange、Queue、Binding、Policy 等定义,不等于备份所有消息数据。
RocketMQ 至少备份:
tar czf rocketmq-conf-backup.tgz conf/消息数据恢复依赖数据目录、主从复制和业务补偿,不要把运行中的 CommitLog 目录简单 cp 一份就当可靠备份。
Kafka 至少导出 Topic 和 ACL:
bin/kafka-topics.sh --bootstrap-server kafka-1:9092 --describe > kafka-topics.txt
bin/kafka-acls.sh --bootstrap-server kafka-1:9092 --list > kafka-acls.txt关键数据流建议用 MirrorMaker、Flink、备份消费程序或对象存储归档做更稳的容灾方案。
恢复演练一定要做最小验证:
# 发一条消息
# 消费一条消息
# 查看积压
# 查看监控
# 查看日志没有演练过的备份,只能叫“看起来有备份”。
落地工程深水区
MQ 上生产后,运维要管的不只是 Broker,还包括 Topic/Queue 生命周期、消费能力、磁盘水位和业务补偿边界。三类 MQ 的命令不同,但治理问题高度相似。
| 维度 | RabbitMQ | RocketMQ | Kafka |
|---|---|---|---|
| 自动创建 | 生产不让业务随手建 queue/exchange | 关闭自动创建 Topic 和订阅组 | 关闭 auto.create.topics.enable |
| 堆积治理 | 看 ready/unacked、消费者数、内存和磁盘告警 | 看 consumer progress、Broker 磁盘和主从状态 | 看 consumer lag、ISR、分区分布 |
| 权限边界 | vhost、user、permission 分环境 | ACL、Topic 权限、Dashboard 只进内网 | ACL、listener、principal 分环境 |
| 恢复边界 | definitions 不是消息备份 | CommitLog 恢复依赖数据目录和复制 | Topic/ACL 可导出,消息容灾靠复制或外部归档 |
现场排障时先用统一口径判断“是 Broker 扛不住,还是消费者不消费”:
# RabbitMQ
rabbitmqctl list_queues name messages_ready messages_unacknowledged consumers memory
rabbitmq-diagnostics alarms
# RocketMQ
sh bin/mqadmin consumerProgress -n namesrv-1:9876
sh bin/mqadmin brokerStatus -n namesrv-1:9876 -b broker-a:10911
# Kafka
bin/kafka-consumer-groups.sh --bootstrap-server kafka-1:9092 --describe --all-groups
bin/kafka-topics.sh --bootstrap-server kafka-1:9092 --describe --under-replicated-partitions工程落地时要把下面四件事前置到上线评审:
- 每个 Topic/Queue 都要有 owner、保留时间、最大堆积预期、扩容方式和删除审批。
- 死信、重试、延迟消息不能替代业务幂等,消费者必须能处理重复投递。
- 磁盘水位告警要早于 Broker 自我保护阈值,留出人工扩容或限流窗口。
- 升级前先确认 Erlang、JDK、客户端 SDK、协议和存储格式兼容性,不在故障窗口内顺手升级大版本。
11. 选型边界
可以按这个简单判断:
| 场景 | 推荐 |
|---|---|
| 普通业务异步、任务队列、路由规则多 | RabbitMQ |
| Java 业务消息、削峰填谷、延迟消息、事务消息能力 | RocketMQ |
| 日志流、事件流、数据管道、超高吞吐、可回放 | Kafka |
| 想用 MQ 长期堆积大量数据再慢慢消费 | 优先 Kafka 或 RocketMQ,RabbitMQ 要谨慎 |
| 需要很友好的管理台和简单队列运维 | RabbitMQ |
| 消费组、分区、副本、流式生态要求高 | Kafka |
不要为了“统一技术栈”强行让一个 MQ 干所有活。业务命令、事件流、日志管道的运维模型不同,故障恢复方式也不同。
12. 上线前检查清单
RabbitMQ:
RocketMQ:
Kafka:
通用:
13. 常用命令速查
RabbitMQ:
rabbitmq-diagnostics status
rabbitmq-diagnostics alarms
rabbitmqctl list_queues -p /prod name messages_ready messages_unacknowledged consumers
rabbitmqctl list_connections name user peer_host state channels
rabbitmqctl list_permissions -p /prodRocketMQ:
sh bin/mqadmin clusterList -n ns1:9876
sh bin/mqadmin topicList -n ns1:9876
sh bin/mqadmin consumerProgress -n ns1:9876 -g order-consumer
sh bin/mqadmin brokerStatus -n ns1:9876 -b broker-a:10911
sh bin/mqadmin topicRoute -n ns1:9876 -t order.createdKafka:
bin/kafka-topics.sh --bootstrap-server kafka-1:9092 --describe
bin/kafka-consumer-groups.sh --bootstrap-server kafka-1:9092 --all-groups --describe
bin/kafka-log-dirs.sh --bootstrap-server kafka-1:9092 --describe
bin/kafka-metadata-quorum.sh --bootstrap-server kafka-1:9092 describe --status
bin/kafka-acls.sh --bootstrap-server kafka-1:9092 --list最后记住一个顺序:先看进程和端口,再看权限和 Topic/Queue,再看积压和磁盘,最后再决定扩容、迁移或恢复。多数 MQ 故障不是一个命令解决的,而是一步一步把现场证据对上。
