Redis主从首次同步必须触发bgsave,因其需提供一致全量快照,而bgsave是唯一不阻塞服务的RDB生成方式;若禁用RDB、磁盘异常或权限不足则失败,导致同步卡住或报错。

主从初次连接时,Redis 为什么必须触发 bgsave?
因为从节点(slave)在首次同步时无法基于增量复制(replication backlog)——它还没拿到任何命令流,主节点只能提供一个完整、一致的快照。这个快照必须是某个时间点的全量内存状态,而 bgsave 是唯一能在不阻塞主节点服务的前提下生成 RDB 文件的方式。
如果主节点禁用了 RDB(比如只配置了 AOF),或者磁盘写入失败、dir 不可写、dbfilename 路径权限不足,bgsave 就会失败,导致同步卡在 WAIT_BGSAVE_START 或直接报错 Failed to create RDB file。
-
bgsave失败时,主节点日志里会出现Failed to save the DB或Can't save in background: fork() failed - 不要手动提前执行
save:它会阻塞所有客户端命令,且生成的 RDB 不会被复制流程自动识别 - 检查
info persistence中的rdb_bgsave_in_progress和rdb_last_save_time,确认bgsave是否真正在运行或刚完成
从节点收到 RDB 后,为什么不能边加载边接收命令?
因为 RDB 是静态快照,加载期间从节点数据库处于“重建中”状态,此时若混入主节点发来的增量命令(如 SET、DEL),会导致数据不一致——比如先删 key 再加载 RDB,key 就永远消失了。
所以 Redis 强制要求:RDB 文件传输完后,从节点先清空当前数据库(flushdb),再解析 RDB 加载,整个过程阻塞所有读写(包括 INFO、CLIENT LIST 等管理命令也会被排队)。这阶段从节点状态是 loading,info replication 显示 master_link_status:up 但 slave_repl_offset:0。
- 大 RDB(>1GB)加载可能耗时几十秒,期间客户端会收到
LOADING Redis is loading the dataset in memory错误 - 避免在高峰期发起全量同步;可通过
repl-diskless-sync yes跳过磁盘,让主节点直接把 RDB 流式传给从节点 socket(但要求网络稳定、带宽充足) - 从节点
config set slave-read-only yes不影响加载期行为——只控制加载完成后是否允许写
repl-diskless-sync 开启后,主节点还调用 bgsave 吗?
仍然调用,但目的变了:bgsave 不再为生成磁盘文件,而是为了 fork 出子进程,把内存数据序列化后直接写进 socket 缓冲区。也就是说,diskless 模式下 bgsave 的输出目标从文件句柄变成了 TCP 连接。
这意味着:即使 dir 不可写、磁盘满,只要 fork 成功、socket 可写,全量同步仍能进行。但它对主节点内存压力更大(需双倍内存暂存序列化数据),且一旦网络中断,整个 RDB 流就废了,得重来。
- 开启 diskless 需同时设置
repl-diskless-sync yes和repl-diskless-sync-delay 5(缓冲几秒,等更多从节点接入,减少重复 fork) - 主节点日志中看到
Background saving started by pid XXX for replication,不代表在写文件,要结合repl-diskless-sync配置判断 - 某些云环境(如容器、无盘实例)默认禁用 fork,此时
repl-diskless-sync也会失败,错误为Fork operation failed
同步过程中,主节点的 repl-backlog 什么时候开始积累命令?
不是连接一建立就开始,而是在主节点完成 bgsave 并开始发送 RDB 数据的那一刻才启动 backlog 缓冲区。也就是说,RDB 生成和传输阶段产生的写命令,都会被追加进 backlog,供后续从节点断线重连时做增量恢复。
但如果从节点迟迟没连上来(比如网络延迟高、认证慢),而主节点又持续写入,backlog 可能被新命令覆盖旧命令(环形缓冲区特性),导致从节点重连后不得不重新全量同步。
- 通过
info replication查看repl_backlog_active:1、repl_backlog_size和repl_backlog_histlen,确认 backlog 是否已启用及剩余空间 - 默认
repl-backlog-size是 1MB,对写入频繁的实例远远不够;建议按「峰值写入带宽 × 期望容忍断连时长」估算,例如 10MB/s × 60s = 600MB - backlog 不占用 RDB/AOF 文件空间,但属于主节点常驻内存开销,调太大可能挤占其他缓存
RDB 文件本身不包含复制偏移量或校验信息,主从之间靠 repl-offset 和 psync 协议握手匹配进度,这点很容易被忽略——你看到 RDB 成功加载了,不代表后续增量一定跟得上。











