复制积压缓冲区(replication backlog)决定了「从库断开多久还能只补差量」。文档里的说法是一个固定大小的环形缓冲。这篇不复述,直接量:把 backlog 设成最小的 16 KB,用一个能随时切断的 TCP 转发让从库断线,看主库写多少字节之后就再也补不上了。
> CONFIG GET repl-backlog-size
1) "repl-backlog-size"
2) "16384"
{'repl_backlog_active': '0', 'repl_backlog_size': '16384', 'repl_backlog_first_byte_offset': '0', 'repl_backlog_histlen': '0', 'master_repl_offset': '0'}
从库连上之后: {'repl_backlog_active': '1', 'repl_backlog_size': '16384', 'repl_backlog_first_byte_offset': '1', 'repl_backlog_histlen': '0', 'master_repl_offset': '0'}没有从库连接过的主库 repl_backlog_active 是 0;第一个从库连上之后变成 1。参数 repl-backlog-size 这里设成 16 KB(CONFIG GET 显示 16384)。
master_repl_offset= 4119 histlen= 4119 first_byte_offset= 1 master_repl_offset= 12055 histlen= 12055 first_byte_offset= 1 master_repl_offset= 16407 histlen= 16407 first_byte_offset= 1 master_repl_offset= 30103 histlen= 30103 first_byte_offset= 1 master_repl_offset= 100119 histlen= 18359 first_byte_offset= 81761
写到 30103 字节时 repl_backlog_histlen 仍等于 offset(30103),已经超过了配置的 16384;写到 100119 字节时才丢头部,histlen = 18359、first_byte_offset = 81761。所以 backlog 实际保留量会略微超过配置值,不是严格的环形缓冲(这一点是从上面的数字看出来的;为什么会这样——猜测是按块分配、整块释放——我没有读源码验证)。
断开期间写入 结果 sync_full partial_ok
1024 部分重同步 0 1 日志累计:Full resync requested 2 次,Partial resynchronization request 1 次
8064 部分重同步 0 1 日志累计:Full resync requested 2 次,Partial resynchronization request 2 次
16000 部分重同步 0 1 日志累计:Full resync requested 2 次,Partial resynchronization request 3 次
20096 部分重同步 0 1 日志累计:Full resync requested 2 次,Partial resynchronization request 4 次
24064 部分重同步 0 1 日志累计:Full resync requested 2 次,Partial resynchronization request 5 次
28032 部分重同步 0 1 日志累计:Full resync requested 2 次,Partial resynchronization request 6 次
32000 全量同步 1 0 日志累计:Full resync requested 3 次,Partial resynchronization request 6 次
40087 全量同步 1 0 日志累计:Full resync requested 4 次,Partial resynchronization request 6 次
64023 全量同步 1 0 日志累计:Full resync requested 5 次,Partial resynchronization request 6 次
100119 全量同步 1 0 日志累计:Full resync requested 6 次,Partial resynchronization request 6 次做法:从库通过一个我写的 TCP 转发连主库;cut() 关闭转发并断开连接,主库继续写入 X 字节,resume() 之后从库自动重连,看主库 INFO stats 里是 sync_partial_ok 还是 sync_full 增加(表里最后一列是主库日志中 Full resync requested 与 Partial resynchronization request 的累计次数,两种判断方式的分类一致)。结果:X 到 28032 字节都是部分重同步——比 16384 大得多;32000 字节起全量同步。断点在本次采样的 28032–32000 之间,没有做更细的二分,也没有多次重复确认边界是否稳定。不要把「16 KB 配置 ≈ 28 KB 可用」当成规律,只当作「实际余量不止配置值」的证据。
> CONFIG GET repl-backlog-size 1) "repl-backlog-size" 2) "1048576" > CONFIG GET repl-backlog-ttl 1) "repl-backlog-ttl" 2) "3600"
默认 repl-backlog-size 是 1048576 字节(1 MB),repl-backlog-ttl 是 3600 秒。每秒写入量 × 预期最长断线时间,再留余量,就是该设的大小。