上周有个朋友半夜给我打电话,说他们公司要做 Redis 迁移,数据量大概 500 GB,问我有没有什么稳妥的办法。电话那头他声音有点急,说明业务不能停太久,最多只能接受十分钟的停机窗口。我一边翻工具箱一边跟他说,这事儿其实没那么玄乎,关键是先弄清楚到底要迁移什么。Redis 看起来简单,不就是个缓存数据库吗,但真动起来,坑比想象中多。

很多人一上来就想着把 AOF 文件或 RDB 文件直接拷过去,觉得跟搬家似的。但 Redis 迁移最麻烦的不是数据本身,而是它背后的业务逻辑。想想,一个生产环境的 Redis,里面可能存着用户登录态、商品库存、秒杀活动的标记,甚至还有 Lua 脚本写的复杂逻辑。如果只把数据搬过去,没考虑客户端连接、数据一致性、内存碎片等问题,迁移完可能比不迁移还惨。我见过最离谱的一次,有人用 SLOWLOG 命令迁移 key,结果跑了三天三夜还没跑完,业务直接崩了。
那到底怎么迁移比较靠谱?其实要看使用场景。最简单粗暴的办法是主从复制,搭建一个从库同步主库的数据,等数据追平后直接切换。这个方案的好处是几乎不影响业务,数据同步是实时的,切换只需要几秒钟。但这里有个细节很多人会忽略:必须确保新老 Redis 版本一致,否则某些数据结构可能不兼容。比如 Redis 6.0 之后加入了 ACL 权限控制,从 5.0 迁到 6.0 时,需要先检查客户端的权限配置。另外,如果主库和从库之间网络延迟大,数据同步会有滞后,贸然切换就会有丢数据的风险。
如果你的 Redis 是单机版,没有主从环境,可以使用工具导出导入。市面上常见的工具有 redis‑dump、redis‑port、RIOT,还有我比较常用的 redis‑migrate‑tool。这些工具的原理差不多,都是扫描源库的所有 key,然后逐个写入目标库。但如果 Redis 里存了大量短期过期的 key(比如秒杀活动的临时 key),在扫描时可能已经过期,导致目标库漏掉。因此在迁移前,最好先统计 key 的过期策略,或者把过期时间统一延长几天,迁移完成后再改回来。
有些场景下甚至不需要迁移全部数据。比如 Redis 只做缓存,用冷启动让业务自行填充即可。但如果是持久化存储,如用户订单信息或配置数据,就必须完整迁移。这时可以先做一次全量迁移,把 RDB 文件拷过去,然后开启 AOF 增量同步,等数据追平后再切换。这样既能保证数据完整,又能把停机时间压到最短。不过要注意,RDB 恢复时如果内存配置不一样,可能触发内存淘汰,导致部分 key 被删除。目标库的内存最好比源库大 20% 以上。
再说说客户端连接的问题。很多人迁移完数据后,业务还是连不上,查了半天原来是连接地址没改。听起来很蠢,但真的有不少人栽过跟头。更麻烦的是,如果业务使用了 Redis 集群模式,迁移就更复杂。集群下数据是通过哈希槽分片的,不能直接把单机的 RDB 文件导入集群,需要使用官方的 命令,或专门的集群迁移工具。而且在集群迁移时,如果某个节点挂掉,整个集群的写入都会受影响,所以必须提前做好备份和容灾。
还有一个容易被忽视的坑:内存碎片。Redis 使用 jemalloc 内存分配器,长时间运行后碎片率可能很高。迁移到新环境后,数据重新加载,碎片率会下降,但这也意味着实际内存占用可能比原来大。我做过一次测试,一个 200 GB 的实例迁移后内存占用变成了 230 GB。因此迁移前要算好目标服务器的内存容量,预留足够余量。迁移后记得执行 命令清理碎片,或调整 参数,防止内存溢出。
如果是跨机房迁移,还要考虑网络延迟和带宽。比如从北京机房迁到上海机房,数据量大时,仅传输 RDB 文件可能需要好几个小时。这时可以搭建中间层,如 Redis Sentinel 或 Codis,让业务先连到中间层,再慢慢切换底层存储。还有一种“土办法”:先压缩 RDB 文件,用 rsync 增量同步,等数据基本一致后再在低峰期切换。跨机房迁移最怕丢数据,最好在迁移完成后写脚本对比源库和目标库的 key 数量以及 CRC 校验和,确保万无一失。
说个我的经验:千万别在周五下午做迁移。别笑,我身边至少有三位同事栽在这上面。Redis 迁移看似简单,却总会出现意料之外的情况。比如某个 key 特别大,扫描时超时;或者客户端连接池没释放,导致新库连接数爆满;再或者迁移过程中源库突然挂掉,数据没完全同步。所以迁移前一定要准备回滚方案,备份好源库的 RDB 文件,万一出问题还能恢复。迁移后要监控一段时间,关注延迟、命中率、内存使用率等指标,确保业务正常。Redis 迁移这事儿,七分准备三分运气,把能想到的坑都填上,剩下的就看运气了。


