恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
CentOS 7下RabbitMQ 3.x升级4.x数据保留实战指南
首页
资讯中心
/
CentOS 7下RabbitMQ 3.x升级4.x数据保留实战指南
CentOS 7下RabbitMQ 3.x升级4.x数据保留实战指南
发布时间:2026/10/15 7:30:45
接手过 RabbitMQ 升级的运维应该都有同感跨大版本升级最磨人的不是软件装不上而是升级完成那一刻你根本不敢确认队列里攒了几十万条消息是不是都还在。这篇文章就是围绕CentOS 7 环境下 RabbitMQ 3.x 升级到 4.x且数据必须保留这件事写的适合自建 RabbitMQ 的运维、后端开发以及被类似任务临时拉去救火的人。标题里数据保留四个字实际包含了三层意思Mnesia 里的元数据不丢、磁盘队列文件里的消息不丢、系统里早就写好的用户权限和策略定义不丢。只靠一个逻辑备份文件是不可能全部兜住的真要一条消息都不损失备份策略、升级路径、验证手段和回滚预案得一次性全部到位。1. 动一次大版本升级前先看清 3.x 和 4.x 之间隔了哪些墙很多人觉得 RabbitMQ 升个级就是卸载旧包、装个新包的事数据目录又不动凭什么会丢。这话对一半。RabbitMQ 的程序改动确实不直接删数据但 3.x 和 4.x 之间隔了好几个硬性条件任何一个不理会都会导致服务起不来、数据目录被反复初始化甚至整个节点被迫重置。1.1 第一道墙Erlang 版本底座整体换掉了RabbitMQ 4.x 对 Erlang/OTP 的最低要求是 26.x而 3.x 时代普遍跑在 Erlang 21 到 25 上。CentOS 7 自带的官方源里基本找不到这么新的 Erlang就算你从 EPEL 拉也大概率拿到一个老版本。这里要注意一个细节RabbitMQ 启动时用的 Erlang 不是你erl -version看到的那个 Erlang而是启动脚本内部解析到的库路径。有些机器上同时装了系统自带的 Erlang、RabbitMQ 官方 Erlang、甚至手动编译的 Erlang升级后启动脚本优先找到哪个直接决定你能不能起来。我在处理这类升级时习惯先把机器上所有 erlang 相关包列一遍再确认/usr/lib64/erlang和/usr/local/lib/erlang这种路径下的实际版本而不是只看 PATH 里的 erl。否则很容易出现我明明装了新 ErlangRabbitMQ 启动却还说 Erlang 版本太低的怪问题。1.2 第二道墙元数据存储和节点类型的思路变了RabbitMQ 4.x 引入了 Khepri 作为可选的元数据存储后端4.1 之后默认就从 Mnesia 迁移到了 Khepri。这带来的直接后果是升级后首次启动会有一段元数据转换/迁移的过程日志里会出现大量和表结构、schema 升级相关的记录。如果此时你手贱执行了rabbitmqctl reset或者数据目录里混入了多余文件迁移就可能半路失败。另外3.x 还允许配置 RAM 节点只把元数据放内存4.x 对这个能力做了收敛和清理。如果你的老集群里有这种特殊节点升级前必须先把节点类型调整回磁盘节点否则升级后节点行为不可预期。还有一点容易被忽略经典镜像队列在 4.x 里已经彻底成为 deprecated 状态新版本还在兼容它但告警日志会一直刷。如果你未来打算把镜像队列迁到仲裁队列quorum queue那是另一个独立工程不要在升级当天混在一起做否则会把问题扩大。1.3 第三道墙CentOS 7 本身已经不是被持续照顾的环境CentOS 7 的社区支持周期结束后很多官方源、第三方源开始清理旧系统的包。你在 CentOS 7 上配置 RabbitMQ 4.x 的 yum 源时有可能发现仓库里已经不再提供 el7 的包或者依赖的 openssl、glibc 版本被系统卡住。这并不意味着完全没法升级但你要做好两个心理准备第一尽量用 RabbitMQ 官方发布渠道提供的、明确标注 el7 可用的 RPM 包而不是无脑 yum update第二升级前确认系统的 openssl 版本满足 4.x 对 TLS 的最低要求否则加密连接相关功能上线后会出问题。2. 把数据保留讲透逻辑备份、物理备份、基线记录各管什么升级方案里最危险的一句话是我已经备份过了。因为 RabbitMQ 的备份有好几种管的事完全不同。在动手升级之前建议把下面这层关系彻底想清楚。2.1 逻辑备份能救什么、不能救什么rabbitmqctl export_definitions导出的 JSON 文件包含用户、VHost、权限、策略、交换机、队列、绑定这些定义类数据。它的好处是清晰、可读、可导入到任意新集群重建拓扑坏处是它完全不包含队列里堆积的消息内容。很多新手会把这份文件当成数据备份等升级后队列消息量对不上才发现 export_definitions 根本帮不上忙。实际项目里我一般是把它当作基线清单来用升级后拿导出的 JSON 和现网做 diff能快速确认拓扑对象有没有少。它能证明你的定义层是完整的但证明不了消息层完整。2.2 物理备份才是消息不丢的真正兜底消息数据存在/var/lib/rabbitmq下的 mnesia 子目录和 queue 存储目录里。要让一条消息都不丢这句话成立必须在升级前对整个数据目录做一份一致性备份。我推荐的做法是熬一个维护窗口先停服务再做冷备份而不是在线 tar。冷备份命令大致是这样systemctl stop rabbitmq-server tar czvf /data/rabbitmq_backup/rabbitmq_data_$(date %Y%m%d).tar.gz /var/lib/rabbitmq tar czvf /data/rabbitmq_backup/rabbitmq_etc_$(date %Y%m%d).tar.gz /etc/rabbitmq systemctl start rabbitmq-server注意/etc/rabbitmq也要备份里面包含了rabbitmq.conf和enabled_plugins。特别是 enabled_plugins决定升级后哪些插件会自动启用少了它管理界面可能直接消失。备份完别急着把 tar 包扔一边至少做一次验证tar tzf看一眼数据目录和 mnesia 子目录在不在。有些环境数据量太大tar 半路报错退出但你没注意到等回滚时才发现整个包是坏的。2.3 升级前的基线记录清单物理备份保住的是数据基线记录保住的是对照标准。建议在停服之前把以下命令的输出全部存成文件升级后逐一比对rabbitmqctl cluster_status rabbitmqctl list_queues name messages messages_ready messages_unacknowledged rabbitmqctl list_exchanges name type durable rabbitmqctl list_bindings source_name destination_name routing_key rabbitmqctl list_users rabbitmqctl list_permissions rabbitmqctl list_policies这些输出文件不需要多复杂纯文本保存即可。升级后只要把这些命令重新跑一遍用 diff 工具对比很快就能定位到哪个对象异常。千万别偷懒只记一个大概有几万条消息后面核对时会很痛苦。2.4 多节点集群的额外准备工作上面说的冷备份方案放在集群里要拆分来看。如果有多台节点可以按逐个节点摘流、停服、备份、离线、等待全部节点备份完成的方式处理。重点是不要在只备份了一个节点的情况下就启动整个集群升级。因为集群的元数据是分布式的单节点备份无法代表集群完整状态。另外.erlang.cookie文件也坐在/var/lib/rabbitmq目录下它会跟着物理备份一起被保住。这个文件是节点间互相认证的凭证丢了它集群里其他节点会直接把你的新节点拒之门外。3. 从停服到启动的完整升级路径换 Erlang、换 RabbitMQ、一次走完下面按单节点的典型流程来写集群节点滚动升级是同一套动作的重复执行差异部分单独放在第 5 节说明。整体原则是先动依赖再动应用最后才动数据。3.1 升级前确认当前版本第一步永远是确认现状。用rabbitmqctl status看两件事RabbitMQ 版本号和 Erlang 版本号。如果当前版本低于 3.13.x我强烈建议你不要直接跨到 4.x。正确路径是先把 3.x 升到 3.13 的最新补丁版让它正常跑几天再走一次本文的升级流程到 4.x。直接 3.8、3.9 跳 4.0 不是完全不可能但中间遇到的元数据兼容问题会多出很多没必要用生产环境去赌。3.2 做冷备份然后停服按第 2 节的方式完成物理备份和基线记录然后执行systemctl stop rabbitmq-server确认进程退出不要凭感觉。rabbitmqctl status如果还能连上说明把进程还活着需要再等一会。注意 state 输出为running不代表进程已经退出要看rabbitmqctl是否报连接错误。3.3 卸载旧 RabbitMQ 服务包不碰数据目录这一步操作对象只是程序包不是数据目录。rpm -qa | grep rabbitmq rpm -e 旧版本的rabbitmq-server包名也可以使用yum remove rabbitmq-server效果等价。这里要强调一个禁忌千万不要在卸载时顺手删除/var/lib/rabbitmq也不要执行任何带purge字样的清理动作。我们的目标是让系统里只留下程序没了但是存量数据原地不动的状态。3.4 把 Erlang 换底到 26.x先看看系统里现在有什么rpm -qa | grep -E erlang|esl-erlang把旧 Erlang 卸载干净。如果之前是用源码编译方式安装的还需要手动确认它的库目录不在 RabbitMQ 的解析路径上。接着安装适合 CentOS 7 新系统环境的 Erlang 26.x。从 RabbitMQ 官方发布渠道找对应 el7 的 RPM 包用rpm -ivh安装或配好源后 yum 安装。安装后验证erl -version按 Erlang 的惯例erl -version输出的是模拟器版本字符串这段字符串中间出现的类似 26.2 的数字才是主版本。同时我习惯再看一眼/usr/lib64/erlang/releases/OTP-26.x是否存在确保库文件确实落到了 RabbitMQ 启动脚本会去找的路径里。3.5 安装 RabbitMQ 4.x先配置后启动安装 4.x 的 RPM 包时如果 yum 源可用就直接yum install rabbitmq-server-4.x否则下载官方 RPM 后 rpm 安装。安装完成后先不要急着一键启动先处理配置对比/etc/rabbitmq/rabbitmq.conf里的参数名和 3.x 时是否一致4.x 对部分旧参数做了改名或移除。如果配置文件里有启动脚本不认识的参数启动会直接报错。我一般先把可疑参数注释掉等启动成功后再一项一项加回来这样能把问题精确锁定在某个参数上。确认enabled_plugins里没有明显不兼容的插件项可以先只保留rabbitmq_management其他自定义插件后续单独处理。确认没问题后再启动systemctl start rabbitmq-server rabbitmqctl await_startup --timeout 60首次启动日志里大概率会出现 schema 升级或者元数据迁移相关的记录这是正常现象。重点观察有没有mnesia相关报错、权限异常、节点名变更。如果是数据量大或队列文件多首次启动会明显慢耐心等不要中途反复重启以免迁移中断留下半截状态。启动成功后立刻检查版本和节点状态rabbitmqctl status确认 RabbitMQ 版本是 4.x、Erlang 版本是 26.x、节点名和升级前一致。到这里软件升级这部分才算真正完成。4. 升级后别急着接流量先做这一组数据核对很多人升级完看到管理界面能打开、队列列表还在就以为大功告成。实际上最该做的核对正是看着一切正常的时候抛给群里的那一句慢着消息数对得上吗4.1 版本与节点名核对先看基础信息。rabbitmqctl status里重点确认节点名是否与升级前一致。如果发现节点名从rabbitold-hostname变成了rabbitnew-hostname说明主机名解析发生了变化集群身份会因此错乱需要先解决主机名问题而不是继续往下验证。4.2 队列消息量的逐项比对把升级前的list_queues输出翻出来重新执行相同命令rabbitmqctl list_queues name messages messages_ready messages_unacknowledged然后逐行比对各队列的 messages 数量。数量一致是最低标准如果出现某个队列消息数减少不要急着下结论先看 messages_ready 和 messages_unacknowledged 的拆分——如果只是 unacknowledged 数量的变化可能是有消息被消费者提前拉走但没有确认这在升级过程中是可能发生的。消息量完全一致也推荐随机抽几个队列用rabbitmqadmin get拉一条消息出来看看业务字段是否正常。注意拉取的时候选择ackmodeack_requeue_true这样消息读出来还会放回队列不会污染线上数据。4.3 拓扑、权限、策略、插件的核对队列消息没问题还要确认定义类没有缺失。建议按这个顺序查rabbitmqctl list_exchanges name type durablerabbitmqctl list_bindings source_name destination_name routing_keyrabbitmqctl list_usersrabbitmqctl list_permissionsrabbitmqctl list_policies每一个都跟升级前的输出对照。特别是 policyRabbitMQ 的路由行为和队列行为很多依赖 policy一旦策略丢失表面上队列还在实际行为已经变化。插件方面确认rabbitmq_management已启用的状态然后访问 15672 端口看管理界面响应。管理界面正常并不代表后端所有插件都正常建议rabbitmq-plugins list看一下还有哪些处于[E]状态和升级前的 enabled_plugins 文件对照。4.4 用一条测试消息验证生产和消费链路结构检查结束后做一次端到端功能验证从测试生产者向一个测试队列发一条消息再由测试消费者消费出来。这条链路如果通说明 Exchange 路由、Queue 存储、连接认证都没问题。如果这条链路都卡住说明升级里还有隐性问题此时不要开始接生产流量。5. 失败时的回滚方案把升级流程反过来走不一定能成功回滚方案是升级前必须写好的不是失败后再想。这里先提醒一句回滚不是把 RabbitMQ 4.x 卸掉装回 3.x这么简单。5.1 为什么换回旧软件不够RabbitMQ 4.x 首次启动时可能会对旧版本的 Mnesia 元数据做转换升级。这个过程一旦发生旧版 3.x 未必能再认新格式的元数据。你可以把数据目录想象成一个档案室新系统进了档案室后给一部分档案换了新的编号规则旧管理员回来只认旧编号档案就找不到了。所以回滚的正确前提是升级之前有一份物理备份/var/lib/rabbitmq回滚时直接用备份覆盖回数据目录而不是指望旧软件能自动理解新数据。5.2 单节点回滚的完整动作步骤大致是这样停止 RabbitMQ 4.x 服务。卸载 4.x 的 rabbitmq-server 包。删除当前/var/lib/rabbitmq目录注意是删除被升级改过的数据不是备份文件。从备份 tar 包解压还原/var/lib/rabbitmq和/etc/rabbitmq。安装回原来的 Erlang 版本和 RabbitMQ 3.13.x 版本。启动服务执行rabbitmqctl status确认回到 3.x。这里有个容易忽略的权限问题解压备份后/var/lib/rabbitmq的属主必须确保是 rabbitmq 用户否则启动时报目录权限错误。5.3 集群回滚为什么更麻烦集群回滚不能只针对一个节点。因为每个节点都参与了元数据同步只要有一个节点已经写入新版本的数据整集群的一致性就都需要重新评估。比较稳妥的做法是如果集群里有一个节点启动后确认异常立刻停掉升级动作其他节点不要再启动 4.x然后对整集群按备份快照做还原。这句话真正想强调的是集群升级前不要只备份正在操作的那个节点必须每个节点都留一份备份否则回滚时缺失节点数据会让你陷入非常尴尬的境地。6. 升级过程中常见的坑我按踩到概率排了序最后聊几个实际操作中真正容易踩到的坑顺序不代表严重程度代表的是常见程度。6.1 Erlang 路径解析到了旧版本机器上同时存在多个 Erlang 时RabbitMQ 启动脚本可能解析到旧路径。表现为安装的 Erlang 明明是 26.x启动后rabbitmqctl status仍显示 25.x 或更低。遇到这个情况优先检查/usr/lib64/erlang和/usr/local/lib/erlang两个路径下的内容然后通过软链接或环境变量统一到新版。不要只盯 PATHRabbitMQ 启动脚本有自己的路径解析逻辑。6.2 逻辑备份被误当成物理备份升级完成、回滚时才发现 export_definitions 导入后队列全是空的这种情况在社区里反复出现。导出定义文件在大部分场景下都会成功因为拓扑结构很轻容易给人已备份的错觉。但队列里的消息是另外一回事。真正遇到问题时唯一能救回消息的只有物理备份。所以我每次升级前都会问自己如果没有物理备份我能不能接受丢失当前所有消息如果不能就去做物理备份。6.3 数据目录属主被破坏升级前手动 tar 打包、回滚时手动解压都可能导致/var/lib/rabbitmq的属主变成了 root而不是 rabbitmq。启动时经常出现莫名其妙的权限报错。执行完解压后先检查一下再启动ls -ld /var/lib/rabbitmq chown -R rabbitmq:rabbitmq /var/lib/rabbitmq注意 chown 不要在服务运行中执行等确认目录状态正常后再启动服务。6.4 旧版插件和新版主程序不兼容自定义插件目录里的 .ez 文件如果是针对 3.x 编译的放到 4.x 里可能直接加载失败。如果升级前启用了这类插件启动时日志会出现未知错误你的第一反应可能是RabbitMQ 坏了实际只是插件不兼容。处理方式是把自定义插件临时移出插件目录等服务正常后再逐个安装对应 4.x 的插件版本。管理界面这类官方插件一般没问题重点排查第三方或内部自研插件。6.5 集群跨版本混跑时间过长滚动升级时集群里必然短暂出现3.x 节点和 4.x 节点共存的阶段。这个阶段可以做但不能拖太久也不要在此期间执行大量的队列创建、删除、绑定修改操作。因为新旧版本对元数据的理解有细微差别混跑期间写操作可能会把不兼容的数据带到新节点。我更建议所有节点在同一个维护窗口内完成升级中间不停业务但严格控制写操作。最后说点实际操作层面的感受。这次升级真正花时间的不是敲命令那几分钟而是备份、验证、回滚思路上。数据保留这件事本质上靠的不是运气而是物理备份 逐项验证 可回滚路径这三个动作同时到位。做完一次之后下次再碰上类似升级你的心态会完全不同。再补一句CentOS 7 已经进入了维护末期这次升级可以理解为存量系统的阶段性续命。升级完成后建议把迁移到更新系统这件事排上日程否则相同的问题只会在未来以更复杂的形式再出现一次。