资讯动态

Redis 6.0升级7.2实战:备份、配置迁移与滚动升级全流程

发布时间:2026/10/6 12:54:00 来源:尧图企业网站定制
前阵子我负责把一台跑了两年的 Redis 6.0.9 升级到 7.2.4后来又把一套三主三从的集群也做了滚动升级。动手之前我以为这就是个替换二进制的活真正做下来才发现最花精力的不是编译而是三件事旧配置怎么翻译成新版本能认的格式、数据怎么备份才能保证升级失败还能回来、主从集群用什么样的顺序切换才不会丢请求。这篇文章就按我当时操作的完整路径来写把你需要提前准备的信息、备份命令、编译步骤、配置迁移、滚动升级顺序、数据校验和回滚方案都列出来。如果你正在维护一台或多台 Linux 上的 Redis准备做版本升级这篇文章应该能帮你少踩几个坑。1. 动手前先搞定三件事需求判断、方案选型、基线信息1.1 先算清楚这笔账Redis 6.0 升 7.2 到底值不值很多同学一听说 Redis 要升级第一反应是“能用就行别乱动它”。说实话Redis 这种承担了缓存、队列、分布式锁的数据组件升级确实有风险但它不是没有理由。我这边升级的动机很直接6.x 已经进入维护末期安全补丁越来越少而 7.2 是 LTS 版本社区还在持续更新。对于承载核心业务缓存的组件来说安全漏洞修复和长期维护支持本身就是硬需求这个理由已经足够说服我了。除了安全层面Redis 7.x 相比 6.x 在生产运维上也有实打实的改进。7.0 开始 AOF 重写采用了 manifest base incr 三段式结构大实例的磁盘压力明显下降内存碎片整理、过期 Key 清理、主从同步这些机制也都做了优化。业务侧如果想要使用 Function 这样更完善的脚本机制或者对 ACL 权限模型有更高要求7.x 也是必经之路。我把两代版本拉了一张简单的对照表对比维度Redis 6.xRedis 7.2官方维护状态维护末期补丁频率下降LTS仍在积极维护AOF 持久化结构单一 AOF 文件manifest base incr 三段式内存与 IO 优化6.0 开始有多线程 IO碎片整理、过期清理更完善脚本能力Lua 脚本支持 Function 机制ACL 与安全基础 ACL更细粒度、更稳定不过我也见过为了升级而升级的团队原本没有明确需求反而把配置文件改错上线后连接错误一堆。所以升级前先问自己三个问题当前版本有没有无法绕过的 bug 或安全漏洞业务需要的新特性是不是只有新版本支持现有生态客户端库、监控脚本、可视化工具、模块能不能兼容新版本如果三个答案都是“没有”那就别动稳定压倒一切。1.2 升级方式选型源码编译、二进制包、发行版仓库哪个靠谱Linux 上装 Redis来源无非就是发行版仓库、官方源码编译、第三方二进制分发这几类。发行版仓库最简单apt install redis-server一条命令就装好但版本往往滞后而且升级路径不完全受自己控制。第三方二进制包虽然方便安全审计时会比较麻烦你很难确认这个包到底怎么构建的、有没有被塞过私货。我自己在生产环境一直坚持官方源码包编译核心原因是可控性和回滚便利性。源码包可以从官方地址下载构建参数自己决定还能装到独立目录比如/usr/local/redis-7.2.4。这样旧版本的完整目录可以原样保留升级只是切换 systemd 或启动脚本的指向万一要回滚把路径切回去就完成了。用包管理器升级的话旧版本文件往往被覆盖回滚就得重新下载旧包麻烦不少。当然了源码编译也有它的门槛。编译机需要安装 gcc、make、pkg-config、tcl 这些基础工具还要处理可能的MALLOC报错。如果生产服务器是一台非常老旧的 Linux 发行版自带编译器版本太旧源码编译可能过不了这时候可以考虑在 Docker 里用较新的基础镜像编译好产物再拷贝到目标机器。不过外部编译的二进制一定要做哈希校验和来源确认别拿一个来路不明的文件替换生产组件。1.3 升级前先给 Redis 拍一张体检照基线信息不能凭感觉升级不是把新版本装上就算完你得能证明升级前后数据是一致的。所以动手之前必须先收集一套完整的基线信息。我习惯用一组 redis-cli 命令快速把实例的“体魄”记下来# 记录版本、运行模式、端口等 redis-cli -a **** --no-auth-warning info server # 内存与碎片率 redis-cli -a **** --no-auth-warning info memory # 命中率与每秒操作数 redis-cli -a **** --no-auth-warning info stats # 持久化状态 redis-cli -a **** --no-auth-warning info persistence # 主从复制状态 redis-cli -a **** --no-auth-warning info replication # Key 总量 redis-cli -a **** --no-auth-warning --scan --pattern * | wc -l # 大 Key 扫描建议低峰期执行 redis-cli -a **** --no-auth-warning --bigkeys # 慢查询记录 redis-cli -a **** --no-auth-warning slowlog get 50这些命令输出里的关键信息我通常会整理成一个小表连接数、内存峰值、碎片率、Key 总量、最大 10 个 Key 的内存占用、慢查询条数、主从延迟、RDB 最近保存时间。升级后同样跑一遍两边对比这就是最朴素也最可靠的数据一致性证据。很多人升级完只确认“能连上、能 get”却说不清有没有丢 Key尤其在大实例上抽样和总量核对必须做。另外别忘了把旧配置文件复制一份到备份目录记录redis-server --version的输出。这一步看起来不起眼但当你需要回滚的时候它就是你的救命稻草。2. 备份、编译与配置迁移最容易翻车的三个环节2.1 备份不是敲一条 BGSAVE 那么简单备份这个环节错误做法是直接在主库上执行 BGSAVE。BGSAVE 确实不阻塞主线程但它要 fork 子进程如果实例内存几十 GBfork 的一瞬间主线程也可能出现明显的卡顿对上游业务来说就是一次几十毫秒到几百毫秒的延迟毛刺。所以我的原则是如果有从节点备份操作一律打到从节点上执行主库保持干净。下面是当时用的完整备份序列# 在从节点上触发 RDB 后台保存 redis-cli -h 127.0.0.1 -p 6379 -a **** --no-auth-warning BGSAVE # 轮询确认后台保存完成rdb_bgsave_in_progress 会变为 0 redis-cli -h 127.0.0.1 -p 6379 -a **** --no-auth-warning info persistence | grep rdb_bgsave_in_progress # 再次确认最近一次成功保存的时间戳 redis-cli -h 127.0.0.1 -p 6379 -a **** --no-auth-warning LASTSAVE # 复制 RDB 文件到带日期的备份路径 cp /var/lib/redis/dump.rdb /backup/redis-dump-$(date %F-%H%M).rdb # 如果 AOF 已开启同时触发一次重写保证文件干净 redis-cli -h 127.0.0.1 -p 6379 -a **** --no-auth-warning BGREWRITEAOF文件复制出来后不要直接扔在那里不管。用 Redis 自带的检测工具跑一遍redis-check-rdb /backup/redis-dump-YYYYMMDD-HHMM.rdb正常输出结尾会看到类似 RDB looks valid 的提示这时候这份备份才算真正可信。还有一个细节很多人会备份错路径建议先用redis-cli config get dir确认 RDB 和 AOF 的真实存放目录再去物理复制文件。同时估算磁盘空间RDB 文件加临时文件加 AOF 重写需要的空间至少留出两到三倍余量。还有一点必须强调RDB 格式在不同大版本之间并不保证向后兼容。Redis 7 能正常加载 Redis 6 产生的 RDB但 Redis 7 一旦重新保存过数据文件旧版本的 Redis 6 未必能读。这意味着升级前的那份 RDB 备份不能删它是回滚路上唯一的“时光机”。2.2 从源码编译 Redis 7.2 的完整过程官方源码包下载和编译的步骤很标准化熟练之后五分钟能跑完但我还是建议一步步来每一步都看一眼输出。以 Redis 7.2.4 为例# 安装编译依赖Debian/Ubuntu 系 sudo apt update sudo apt install -y build-essential tcl pkg-config libsystemd-dev # 下载官方源码包 wget https://download.redis.io/releases/redis-7.2.4.tar.gz # 解压 tar xzf redis-7.2.4.tar.gz cd redis-7.2.4 # 并行编译 make -j$(nproc) # 安装到独立目录避免覆盖旧版本 make install PREFIX/usr/local/redis-7.2.4如果需要启用 TLS 支持编译时要追加make BUILD_TLSyes同时提前装好 libssl-dev。编译完成后先确认版本号和二进制完整性/usr/local/redis-7.2.4/bin/redis-server --version如果 make 过程中报错而且错误信息里能看到 malloc 或 jemalloc 相关字样多半是当前环境的 jemalloc 源码编译不通过可以改成系统自带的内存分配器make distclean make MALLOClibc老旧 Linux 发行版自带 GCC 版本太低也会让 Redis 7.x 编译失败这种情况下我建议换成在 Docker 等较新的环境里编译好产物再拷过来。编译产物会被打进 Docker 镜像里拷出时要保持目录结构完整。安装完后systemd 服务文件也需要更新。我当时的服务文件长这样[Unit] DescriptionRedis Server Afternetwork.target [Service] Typenotify ExecStart/usr/local/redis-7.2.4/bin/redis-server /etc/redis/redis.conf --supervised systemd ExecReload/bin/kill -s HUP $MAINPID TimeoutStopSec0 LimitNOFILE65535 Restarton-failure [Install] WantedBymulti-user.target这里有一个很多人踩过的坑如果使用了 systemd 的 Typenotify 模式Redis 配置文件里的daemonize必须设置为 no否则 systemd 会认为进程启动失败陷入不断重启的循环。启动参数里加--supervised systemd就是为了让 Redis 以 systemd 通知模式运行。2.3 配置迁移旧参数哪些要删、哪些要改升级过程中真正的隐形杀手是旧配置文件。我那次升级就撞上了一个典型问题旧配置里写了aof-use-rdb-preamble no结果新版本启动直接报Bad directive or wrong number of arguments。原因很简单Redis 7.x 把 AOF 混合持久化固定为开启这个开关已经被移除了旧配置反而成了绊脚石。所以配置迁移的正确姿势不是拿旧 conf 直接启动而是先做兼容性检查。我把生产环境的旧配置和官方 7.2 示例配置做了一次 diff把差异逐项过一遍重点检查这几类检查项升级前要确认的事daemonize / supervisedsystemd 环境下必须 daemonize noaof-use-rdb-preamble新版本已固定开启配置里出现会报错rename-command确认命令名在新版本中没被移除或改名ACL 文件路径users.acl 文件权限和格式是否兼容TLS 配置证书路径、协议参数有没有变更dir / logfile / pidfile目录是否存在且有写权限检查完之后我强烈建议先在前台启动一次redis-server /etc/redis/redis.conf --daemonize no前台启动时所有配置错误、依赖问题都会直接打在日志里。等看到 Ready to accept connections 字样再 CtrlC 停掉然后交给 systemd 正式启动。这一步看似多花三十秒实际能省下后面一晚上的排查时间。3. 升级实施与验证单机与集群的实操顺序3.1 单机升级执行步骤照着做不会乱单机升级的路径相对简单但每一步都有它的目的。我按当时操作的顺序整理如下通知业务方确认升级窗口内没有写入流量或者已经由网关层把写请求切到其他集群。Redis 升级窗口内最理想的状态是只读、零流量。执行上一节讲到的备份流程RDB 和 AOF 都备份并且跑完 redis-check-rdb。这一步没有完成之前绝对不要碰服务。停止 Redis 服务sudo systemctl stop redis。如果服务器上同时存在 init.d 脚本和 systemd 服务要确认你用的管理方式和实际启动方式一致避免停了个寂寞。备份原可执行文件目录sudo mv /usr/local/redis /usr/local/redis-6.0.9。保留原始目录是回滚的基础。把新版本安装到 /usr/local/redis-7.2.4修改 systemd 服务文件里的 ExecStart 路径。前台试启动确认没有配置报错再通过 systemd 正式启动。启动后立刻查看日志确认 Ready to accept connections 出现没有 ERROR 级别输出。做数据校验和功能回归确认通过后再切业务流量。业务连接地址、密码、证书切换到新实例先灰度一小部分请求观察客户端日志没有异常再全量放量。我见过有人在第 6 步偷懒直接systemctl start。结果旧配置某个参数不兼容新进程反复退出systemd 也一直在重启日志里全是 Bad directive场面非常混乱。前台启动一遍能把这些报错一次性亮出来处理起来从容很多。3.2 主从与集群滚动升级顺序决定了会不会丢数据对于简单的主从复制架构升级顺序的原则是先从后主。先把所有从节点升级到新版本确认从节点的复制 offset 已经追上主节点再挑一个从节点提升为主。以 Redis 官方命令来说就是# 确认从节点追上主节点 redis-cli -a **** --no-auth-warning info replication | grep -E role|master_repl_offset # 手动触发一次无损故障转移 redis-cli -a **** --no-auth-warning CLUSTER FAILOVER执行 CLUSTER FAILOVER 后原来的从节点会变成主节点旧主节点降级为从。此时把旧主节点也升级到新版本整个主从架构就完成了滚动升级。这个顺序最重要的一点是在切换过程中始终有一个可用的主节点在承担写入不会出现同时把两个节点都停掉的空窗期。如果是完整的三主三从 Redis Cluster操作逻辑类似但更讲究节奏。开始之前先跑一次redis-cli -a **** --no-auth-warning --cluster check 127.0.0.1:7000确认cluster_state:ok所有分片都健康。然后把每个分片的从节点逐个升级每升级完一台都要等它把数据同步追平再继续下一台。最后逐个对主节点做 FAILOVER再升级原主节点。整个过程中不要同时让两个主节点处于重启状态避免集群内部触发选举抖动。过渡期间不同版本节点共存是集群滚动升级的正常状态但别让新旧版本长期混跑全部升级完成后才算真正稳定。3.3 数据一致性校验与功能回归清单升级完成后最紧张的时刻来了数据到底有没有丢。我一般分两层来验证。第一层是总量对比# 升级前记录过的 Key 总量升级后再跑一次 redis-cli -a **** --no-auth-warning --scan --pattern * | wc -l # 每个库的 Key 数分布 redis-cli -a **** --no-auth-warning info keyspace如果升级前是 83 万个 Key升级后变成了 82 万那就说明有问题哪怕只差一个也要查到底。第二层是抽样比对挑几个业务核心 Key对比类型、TTL、值是否一致for k in user:1001 user:1002 order:20240101:1001; do echo $k redis-cli -a **** --no-auth-warning type $k redis-cli -a **** --no-auth-warning TTL $k redis-cli -a **** --no-auth-warning get $k done数据验证通过之后还要做一轮业务功能回归。很多同学只测 get/set但 Redis 里还有 List、Hash、ZSet、Stream 一堆数据结构老版本有一种编码叫 ziplist新版本改成了 listpack虽然数据能读出来但接口行为、内存占用可能都不一样。我每次升级都会快速把各类型都操练一遍数据类型验证操作Stringset、get、incr、expireHashhset、hgetall、hlenListlpush、lrange、llenSetsadd、smembers、scardZSetzadd、zrangebyscore、zscoreStreamxadd、xread、xlenBitmapsetbit、getbitHyperLogLogpfadd、pfcountGeogeoadd、geodist业务侧还要单独验证两个常见场景一个是缓存治理相关的淘汰策略我会设置一个很小的 maxmemory触发allkeys-lru确认 Redis 能正常选 Key 淘汰并且不报错另一个是分布式锁用SET lock:key uuid NX PX 10000模拟加锁确认只有持锁方才能通过 Lua 脚本或事务完成 DEL防止误删。这两类场景是生产里最常见的用法漏测概率不高但一旦出问题影响面很大。最后再用可视化客户端比如 Redis Desktop Manager 或者 Another Redis Desktop Manager 连一次看连接信息、慢日志、内存图表是否正常确保运维团队日常使用的工具链也没断档。4. 问题排查、回滚与升级后的日常养护4.1 高频报错与排查实录升级过程中我记忆里最深的几个报错整理成了一张速查表给后来人当参考现象可能原因处理方式make 报错包含 malloc/jemalloc 关键字当前环境编译 jemalloc 失败make distclean后make MALLOClibc启动报 Bad directive旧配置含新版本移除或改名的参数对照 7.2 官方示例配置逐一修正日志显示 Cant open the log filelogfile 目录不存在或权限不足创建目录并 chown 给运行用户本地连接被拒绝bind 或 protected-mode 限制确认进程在跑再按要求调整 bind 和 protected-mode客户端报 READONLY 错误主从切换后客户端仍连着旧主节点客户端或代理层按集群 slot 重定向磁盘满导致 RDB 保存失败备份文件或 AOF 重写占满磁盘清理磁盘修复持久化路径还有一个小经验升级后立刻关注日志里的 WARNING 和内存碎片率。新版 Redis 的内存碎片整理算法和 jemalloc 版本都有变化RSS 出现短期波动是正常现象先观察activedefrag是否开启不要一看到内存上涨就急着回滚。客户端协议层面也要注意Redis 7.x 默认仍是 RESP2老的客户端库基本都兼容千万不要为了尝鲜马上把连接切换到 RESP3除非你已经确认客户端库完整支持 RESP3 的推送和类型系统否则会看到一堆协议解析错误。4.2 回滚预案升级前不准备出事时只能赌升级这件事我给自己立过一个硬性要求升级方案和回滚方案必须同时准备而且回滚方案要写成步骤贴到交付文档里。操作前五分钟再读一遍回滚步骤比临时翻历史命令靠谱得多。单机环境的回滚其实不复杂停止新版本进程。把二进制目录从 /usr/local/redis-7.2.4 切回原来的 /usr/local/redis也就是恢复旧版本可执行文件。恢复旧配置文件。把新版 Redis 写入过的 dump.rdb 和 AOF 文件先移走再复制回升级前备份的那份 RDB/AOF。启动旧版本立刻做数据校验。关键点在第 4 步。很多人回滚只换了二进制却忽略持久化文件已经被新版本动过。Redis 7 重新保存后的 RDBRedis 6 未必能读如果直接把旧二进制配上新生成的 RDB 启动很可能加载失败或者加载出完全乱掉的数据。所以回滚时必须连数据文件一起回退。对于集群环境回滚的原则是“保存主战场”。如果在滚动升级中段发现异常立即停止后续节点的升级已经升级过的节点可以留在集群里继续当从节点但核心数据节点保持在旧版本不动。这样即使后面要回滚也只是把已升级的节点再切回来不会影响主数据链路。要记住回滚会丢失升级完成后产生的增量写入因此升级窗口必须足够短业务写入要能暂停或者切换。4.3 升级后的运维习惯版本升级不是终点Redis 升级完成、业务验证通过我通常还会做两件事补一波日常运维规范把这次的经验沉淀下来。第一件事是建立定期备份机制。光有一次升级前的备份不够我建议每天定时对从节点执行 BGSAVE保留最近 7 天的 RDB 文件每周跑一次 redis-check-rdb。备份的存在意义不取决于文件在不在而取决于能不能恢复定期在临时环境做一次恢复演练才能真正验证备份链路。第二件事是大 Key 治理和缓存治理的常态化。升级后我重新跑了一次redis-cli --bigkeys把超过阈值的大 Key 列出来和业务方逐个确认是否可以拆分、压缩或者做冷热分层。Redis 是内存数据库放任大 Key 膨胀就是在给自己埋雷。缓存治理上我会重新审视 maxmemory 和淘汰策略给每台实例留出内存应急缓冲避免某个热点 Key 突发写入直接打满内存。慢日志也不要忽略。升级后慢查询分布变了用SLOWLOG GET 100看一遍耗时靠前的命令把slowlog-log-slower-than设置成合适的阈值保持对性能问题的敏感度。版本和安全公告那边定期看一眼 Redis 官方 release notes 和 CVE 列表不要把升级拖成一年一次的大工程小版本有安全补丁就及时打上大版本跨越时再走完整的升级演练。我个人在实际操作里最深的体会是升级这个动作本身不复杂复杂的是你得知道每一步为什么这么做。备份为什么一定要在从节点做启动为什么一定要先前台跑一遍回滚为什么一定要连持久化文件一起处理把这些“为什么”想清楚版本升级就从一件让人紧张的事变成了一个可以写进 SOP 的常规操作。后面我计划把整套流程整理成自动化脚本以后再做 Redis 升级就是一件不慌不忙、按部就班的事。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑