传统的全量同步要先把 RDB 写到主库磁盘,再读出来发给从库。无盘复制(diskless)让子进程直接把 RDB 写进从库的连接。新版本里它已经是默认值——而且默认带一个 5 秒的等待。这篇量一量它对同步时间的影响,以及那 5 秒是干什么的。
> 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。
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,两种无盘配置没有。
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 是这个版本日志里出现的目标名,我没有深入验证它对应的协议细节。
从库 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 一次。代价是单个从库的同步被推迟。
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,同样是单次测量)。