bigywater.tech
Redis · 58

无盘复制

传统的全量同步要先把 RDB 写到主库磁盘,再读出来发给从库。无盘复制(diskless)让子进程直接把 RDB 写进从库的连接。新版本里它已经是默认值——而且默认带一个 5 秒的等待。这篇量一量它对同步时间的影响,以及那 5 秒是干什么的。

5.81 s
默认配置(delay 5)下的同步耗时;delay 0 是 0.29 s
无 dump.rdb
无盘发送时,主库磁盘上不产生 RDB 文件
1 次
延迟窗口内先后到达的两个从库,共用的 BGSAVE 次数

先看默认值

实测 · 本机执行输出
> CONFIG GET repl-diskless-sync
1) "repl-diskless-sync"
2) "yes"
> CONFIG GET repl-diskless-sync-delay
1) "repl-diskless-sync-delay"
2) "5"
> CONFIG GET repl-diskless-sync-max-replicas
1) "repl-diskless-sync-max-replicas"
2) "0"
> CONFIG GET repl-diskless-load
1) "repl-diskless-load"
2) "disabled"

这台机器上的 Redis 默认:无盘发送 repl-diskless-sync yes,等待 repl-diskless-sync-delay 5(秒),repl-diskless-sync-max-replicas 0,从库加载 repl-diskless-load disabled。

同步耗时:磁盘 vs 无盘 vs 默认延迟

30 万个 key,每种配置一个新主库 + 一个新从库
实测 · 本机执行输出
 disk: 从库同步完成耗时 0.36 s;主库磁盘上有 dump.rdb: True
  dl0: 从库同步完成耗时 0.29 s;主库磁盘上有 dump.rdb: False
  dl5: 从库同步完成耗时 5.81 s;主库磁盘上有 dump.rdb: False

磁盘方式 0.36 s,无盘 delay 0 0.29 s,两者接近(单次测量,差别在噪声范围内,我没有多次重复);默认的无盘配置是 5.81 s——多出的 5 秒是 delay,不是传输慢。磁盘方式时主库目录里留下了 dump.rdb,两种无盘配置没有。

那 5 秒在等什么

实测 · 本机执行输出
   Delay next BGSAVE for diskless SYNC
   Starting BGSAVE for SYNC with target: replicas sockets (rdb-channel)
   BGSAVE done, 300000 keys saved, 0 keys skipped, 12781649 bytes written.
   Streamed RDB transfer with replica 127.0.0.1:7180 succeeded (socket). Waiting for REPLCONF ACK from replica to enable st

日志里先是 Delay next BGSAVE for diskless SYNC,延迟结束后才 Starting BGSAVE for SYNC with target: replicas sockets (rdb-channel):子进程把 RDB 直接写到从库的连接上;最后 Streamed RDB transfer with replica … succeeded (socket)。这里的 rdb-channel 是这个版本日志里出现的目标名,我没有深入验证它对应的协议细节。

延迟窗口就是为了共用

延迟设 3 秒,第二个从库晚 1 秒到
实测 · 本机执行输出
从库 A 完成 2.74 s,从库 B 完成 2.74 s;主库 "Starting BGSAVE for SYNC" 次数 = 1(两个从库)
   Delay next BGSAVE for diskless SYNC
   Delay next BGSAVE for diskless SYNC
   Starting BGSAVE for SYNC with target: replicas sockets (rdb-channel)
   BGSAVE done, 300000 keys saved, 0 keys skipped, 12781621 bytes written.
   Streamed RDB transfer with replica 127.0.0.1:7184 succeeded (socket). Waiting for REPLCONF ACK from replica to enable st
   Streamed RDB transfer with replica 127.0.0.1:7185 succeeded (socket). Waiting for REPLCONF ACK from replica to enable st

两个从库的完成时间都是 2.74 s、2.74 s,主库日志只有 1 次 Starting BGSAVE for SYNC,然后两次 Streamed RDB transfer:一个子进程,同一份 RDB,发给了两个从库。这就是等待窗口的用途——多个从库同时上线(比如主库重启后所有从库一起重连)时只 fork 一次。代价是单个从库的同步被推迟。

从库端:repl-diskless-load

实测 · 本机执行输出
 disabled: 同步 0.29 s;从库目录里的文件:['dump.rdb', 'redis.conf', 'redis.log']
   swapdb: 同步 0.11 s;从库目录里的文件:['redis.conf', 'redis.log']

默认 disabled:从库先把收到的 RDB 落成 dump.rdb,再加载;目录里能看到这个文件。swapdb:同步之后目录里没有 dump.rdb,说明从库没有把收到的 RDB 落盘(同步 0.11 s,对比 0.29 s,同样是单次测量)。

分步演示:五个对比

无盘复制
本步的数据

    本文用到的工具与边界

    • 本机 macOS 27 / Redis 8.10.2 独立实例(本机回环端口,save 关闭),redis-cli 风格输出由自写的 RESP 客户端打印;计时用 time.perf_counter,数字每次运行会有小幅抖动。每种配置一个新的主库(30 万个 key,value 是随机小数字符串)和新从库,本机回环;每种配置只测一次,差别很小的数字不要当结论
    • 没有验证:跨机器网络下无盘与磁盘方式的差别、repl-diskless-sync-max-replicas 提前触发、rdb-channel 的协议细节、swapdb 加载失败时的回滚、大数据集下无盘对主库内存(COW)的影响
    京ICP备2026067502号-1京公网安备11010502063487号