Redis 主从复制中 replication buffer 和 repl backlog 的区别

在 Redis 主从复制的面试中,replication bufferrepl backlog 是一对极易混淆的概念。很多候选人能说出“一个用于全量同步,一个用于增量同步”,但再往下追问“它们分别分配在哪个节点上”“什么时候创建、什么时候释放”“为什么有了 replication buffer 还需要 repl backlog”,就开始含糊其辞了。

这篇文章会从主从复制的整体流程切入,把这两个缓冲区的定位、生命周期、内存行为以及常见面试追问一次性讲清楚。

先看主从复制的整体流程

Redis 主从复制分为两个阶段:

  1. 全量同步(Full Resynchronization):从节点第一次连接主节点,或者断线太久无法增量同步时,主节点会 fork 出子进程生成 RDB 文件发送给从节点。
  2. 增量同步(Partial Resynchronization):从节点短暂断线后重连,如果条件满足,主节点只发送断线期间缺失的写命令,而不需要重新传 RDB。

这两个阶段分别对应了今天要讲的两个缓冲区:

  • replication buffer:全量同步期间,主节点用来缓存“RDB 生成之后、从节点加载 RDB 完成之前”这段时间内产生的新写命令。
  • repl backlog:主节点上维护的一个固定大小的环形缓冲区,用于支持增量同步,保存最近一段时间的写命令。

replication buffer 是什么

定位与创建时机

replication buffer主节点为每一个从节点单独维护的一个缓冲区。当主节点执行 BGSAVE 生成 RDB 时,从节点还没有收到并加载完 RDB,但主节点不可能停止处理写请求。这段时间内所有新的写命令,都会被写入对应从节点的 replication buffer 中。

等从节点加载完 RDB 后,主节点再把 replication buffer 中积累的命令发送过去,从而保证主从数据一致。

关键特征

  • 每个从节点一份:主节点有 N 个从节点,就有 N 个 replication buffer(严格说是每个从节点的输出缓冲区 client output buffer 的一部分)。
  • 动态增长:大小不固定,取决于全量同步耗时和写入量。同步期间写入越频繁、RDB 越大传输越慢,这个缓冲区就越大。
  • 可配置上限:通过 client-output-buffer-limit replica 参数限制。如果超过硬限制,主节点会强制断开该从节点连接,避免主节点内存被撑爆。
  • 生命周期短:全量同步完成后,缓冲区中积累的数据发送完毕,这部分内存就会被释放(或回收到正常复制流中)。

一个容易忽略的点

replication buffer 并不只存在于全量同步阶段。在正常复制流中,主节点向从节点发送命令时,如果从节点处理慢,命令也会堆积在输出缓冲区里。所以更准确的说法是:全量同步阶段它会显著增长,是内存风险的高发期,而日常复制中它一直存在但通常很小。

repl backlog 是什么

定位与创建时机

repl backlog主节点上全局唯一的一个环形缓冲区(circular buffer),在第一个从节点连接时创建,之后一直存在(只要还有一个从节点)。

它保存的是主节点最近产生的一批写命令。每个命令还会附带一个 master_repl_offset(复制偏移量)。从节点断线重连时,会带上自己已经处理的偏移量,主节点检查这个偏移量是否还在 backlog 范围内:

  • 如果在,说明断线期间的命令都还在 backlog 里,可以执行增量同步,只补发缺失部分。
  • 如果不在(被环形缓冲区覆盖了),只能退化为全量同步

关键特征

  • 全局唯一:不管有多少个从节点,主节点只有一个 repl backlog。
  • 固定大小:由 repl-backlog-size 配置,默认 1MB。它是环形结构,写满后新数据覆盖旧数据。
  • 长期存在:只要主节点还有从节点,backlog 就一直保留。所有从节点都断开后,经过 repl-backlog-ttl(默认 3600 秒)才会被释放。
  • 目的明确:专门为增量同步(PSYNC)服务,是“断线重连能否快速恢复”的关键。

核心区别对比

维度 replication buffer repl backlog
数量 每个从节点一个 全局唯一
分配位置 主节点 主节点
主要用途 全量同步期间缓存新写命令 支持增量同步(断线重连)
大小 动态增长,可配上限 固定大小(环形)
生命周期 随从节点连接创建/释放 第一个从节点连接时创建,长期存在
溢出后果 主节点断开该从节点 从节点无法增量同步,退化为全量同步
相关配置 client-output-buffer-limit replica repl-backlog-sizerepl-backlog-ttl

为什么有了 replication buffer 还需要 repl backlog

这是面试中最常被追问的问题,也是理解两者关系的关键。

replication buffer 解决的是一次全量同步过程中的数据一致性问题,它的生命周期和某一次同步绑定。一旦从节点断开,这个 buffer 就没了。

repl backlog 解决的是从节点断线重连后能否快速恢复的问题。如果只有 replication buffer,从节点每次断线都必须重新全量同步,代价极高(fork、生成 RDB、传输、加载)。有了 backlog,短时间断线可以走增量同步,大幅降低开销。

换句话说:

  • replication buffer 面向“同步过程”,保证全量同步不丢数据。
  • repl backlog 面向“断线恢复”,保证增量同步可行。

两者服务的目标不同,缺一不可。

常见面试追问

追问一:主节点内存暴涨通常和哪个有关?

多数情况是 replication buffer。全量同步期间写入量大、从节点加载慢,缓冲区持续膨胀,可能触发 client-output-buffer-limit 导致从节点被断开,甚至拖垮主节点。调大 backlog 一般不会导致内存暴涨,因为它是固定大小的。

追问二:repl backlog 设置多大合适?

经验公式:repl-backlog-size = 平均写入速率 × 预计最长断线时间。比如平均每秒写入 1MB,预计从节点最长断线 60 秒,那 backlog 至少设为 60MB。设太小会导致频繁全量同步。

追问三:从节点也会有 backlog 吗?

repl backlog 只在主节点上维护。从节点本身不创建 backlog,但它有自己的复制偏移量,用于重连时向主节点请求增量同步。

追问四:全量同步时,命令是先写 replication buffer 还是先写 backlog?

两者都会写。主节点在处理写命令时,会同时把命令传播给所有从节点的输出缓冲区(含 replication buffer),并追加到 repl backlog。它们是并行写入的,不是二选一。

总结

一句话概括:replication buffer 是主节点为每个从节点在全量同步期间准备的“临时蓄水池”,repl backlog 是主节点为所有从节点共享的、用于断线重连增量同步的“固定环形日志”。

理解这两个概念,不仅要记住定义,更要抓住三个关键:分配粒度(每从节点 vs 全局)、大小策略(动态 vs 固定)、服务目标(全量同步 vs 增量同步)。面试时能把这三点讲清楚,基本就能拿下这道题。

未经允许不得转载:任鹏个人博客 » Redis 主从复制中 replication buffer 和 repl backlog 的区别

赞 (0) 打赏

评论 0

取消
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏