先来聊聊一个让不少运维同学头疼的场景:Redis RDB 快照文件明明存在,服务也能启动,但数据就是出不来。这背后通常藏着两个典型问题——版本不兼容和字节序误判。下面逐一拆解。

Redis 启动时卡在“Reading RDB file”无报错,但 dbsize 为 0
这种情况非常典型,就是 RDB 版本不兼容。尤其是高版本 Redis(比如 7.0+)生成的 RDB 文件,头部标记为 REDIS0011,而低版本 Redis 加载时,解析器在校验头部后直接静默退出——既不报 ERROR,也不加载任何数据。日志停在 Reading RDB file,用 redis-cli dbsize 一查,始终是 0。这就是所谓“无声的失败”。
实操建议:
- 用
head -c 10 dump.rdb | hexdump -C看一眼前 10 字节:如果出现52 45 44 49 53 30 30 31 31(即REDIS0011),基本确认是 Redis 7.0+ 生成的 RDB。 - 检查当前 Redis 版本:
redis-server --version,如果低于 7.0,那基本可以锁定问题。 - 千万别试图手动修改 RDB 文件头——校验和会失效,Redis 启动直接 abort。
- 临时解法:在同版本 Redis 实例上导出数据(
redis-cli --scan --pattern '*' | xargs -L 1000 redis-cli MIGRATE),再导入目标版本。
redis-check-rdb 提示“Invalid magic number”,但文件能被同版本 Redis 加载
这个现象更迷惑:工具报错说魔法数字无效,可 Redis 服务进程却能正常加载。原因往往不是文件损坏,而是字节序(endianness)误判。RDB 文件本身就是小端序(little-endian)编码,但 redis-check-rdb 早期版本(v0.1.15 之前)在部分 ARM 架构或旧版 macOS 上会错误解析 magic 头,导致报 Invalid magic number,而实际 Redis 服务进程能正常加载数据。
实操建议:
- 先验证 Redis 能否加载:
redis-server --dbfilename dump.rdb --port 6380,然后连上去执行KEYS *,看是否返回结果。 - 升级工具:
pip install --upgrade rdbtools,最新版已修复 ARM64/Apple Silicon 平台的字节序识别。 - 如果只是想导出数据,可以绕过检查:直接用
rdb -c json dump.rdb,它不依赖 magic 校验,只流式解析有效记录。 - 注意:这个问题和跨平台无关——RDB 规范明确要求小端序,Linux/x86、macOS/ARM、Windows/WSL 均一致,不存在“Windows 生成的 RDB 在 Linux 打不开”这类字节序问题。
从 AIX 或旧 Solaris 迁移 RDB 文件后加载失败
极少数场景下,某些企业级 Unix 系统(如 AIX 7.1 + Redis 4.0 定制版)曾输出过非标准 RDB:头部 magic 正确,但内部数据库编号字段用了大端序写入,导致 Linux 上 Redis 解析时 key 数量错乱、提前遇到 EOF。现象是 redis-check-rdb --stat 显示 key_count: 0 或负数,且 total_size 远小于 ls -l 结果。
实操建议:
- 用
redis-check-rdb --verbose dump.rdb 2>&1 | head -n 20观察解析中断位置,如果卡在select db 0之后第一个 key 前,高度疑似该问题。 - 不推荐手动翻转字节——RDB 中混合字符串、整数、长度前缀,翻转风险极高。
- 唯一稳妥路径:在原系统上启动同版本 Redis,用
redis-cli --rdb /dev/stdout > dump-fixed.rdb重新序列化一次(该命令强制按当前平台规范重写)。 - 后续规避:所有跨 Unix 变体迁移,统一走
SCAN + DUMP/RESTORE管道,避开 RDB 二进制层。
为什么“跨平台兼容”不等于“跨版本兼容”
RDB 跨平台(Linux/macOS/Windows)没问题,是因为 Redis 实现严格遵循小端序 + 固定结构对齐。但跨版本失败,核心原因是 Redis 主动迭代了 RDB 格式:7.0 加了 LFU 计数器字段,6.2 加了 module 元数据块,5.0 开始支持 stream 类型编码。这些新增字段,低版本解析器根本无法跳过,只能终止。
还有一个容易被忽略的点:redis-check-rdb 的兼容性其实比 redis-server 更弱——它可能连 6.2 的 RDB 都报 unknown opcode,但 Redis 6.0 服务进程反而能加载(因为有向后兼容的降级逻辑)。所以别把工具报错等同于文件不可用,实践才是检验真理的唯一标准。
