Redis 主从复制:基本概念与工作流程 – wiki基地


Redis 主从复制:深入理解基本概念与工作流程

Redis 作为当今互联网技术栈中不可或缺的高性能键值存储数据库,广泛应用于缓存、消息队列、排行榜、分布式锁等多种场景。为了确保服务的高可用性、提高读取性能以及实现数据冗余备份,Redis 提供了多种机制,其中 主从复制(Master-Slave Replication) 是最基础也是最核心的机制之一。它构成了 Redis Sentinel(哨兵)和 Redis Cluster(集群)实现高可用和分布式能力的基础。本文将详细阐述 Redis 主从复制的基本概念、工作流程、关键技术点以及其优缺点。

一、 什么是 Redis 主从复制?

Redis 主从复制是一种数据同步机制,允许一个 Redis 服务器(称为 从节点 (Slave/Replica))精确地复制另一个 Redis 服务器(称为 主节点 (Master))的数据。

在这种架构中:

  1. 主节点(Master):通常负责处理写操作(如 SET, DEL, INCR 等),并将数据的变更记录同步给所有连接的从节点。一个主节点可以拥有零个、一个或多个从节点。
  2. 从节点(Slave/Replica):通常配置为只读模式(replica-read-only yes 是默认设置),负责处理读操作(如 GET, LRANGE 等),从而分担主节点的读压力。从节点接收来自主节点的数据更新,并保持与主节点数据的一致性(最终一致性)。

通过主从复制,可以实现以下主要目标:

  • 数据冗余与备份:从节点是主节点数据的实时(或接近实时)副本,当主节点发生故障时,从节点可以提供数据备份,甚至可以被提升为新的主节点,减少数据丢失风险。
  • 读写分离,负载均衡:将读请求分散到多个从节点处理,降低主节点的访问压力,显著提高应用的整体读取性能和吞吐量。写请求仍然由主节点处理。
  • 高可用性基础:主从复制是 Redis Sentinel 和 Redis Cluster 实现自动故障转移和高可用性的基础。Sentinel 会监控主从节点的状态,并在主节点宕机时自动将一个健康的从节点提升为新的主节点。

二、 主从复制的核心概念

理解主从复制的工作流程,需要先掌握几个关键概念:

  1. Replication ID (Run ID):每个 Redis 实例启动时都会生成一个唯一的、长度为40个字符的随机字符串,称为 Run ID。当一个实例首次成为主节点时,它的 Run ID 会被用作 Replication ID。这个 ID 标识了主节点数据集的一个特定“历史版本”。如果主节点重启或角色改变(例如,一个从节点被提升为新的主节点),它的 Run ID 会改变,从而 Replication ID 也会改变。从节点在连接主节点时会记录下主节点的 Replication ID。
  2. 复制偏移量 (Replication Offset):主节点和从节点都会维护一个复制偏移量。
    • 主节点偏移量:表示主节点向从节点发送的复制流(命令字节流)的总字节数。每当主节点向从节点发送 N 个字节的数据时,其偏移量就增加 N。
    • 从节点偏移量:表示从节点已从主节点接收并处理的复制流的总字节数。
      从节点会定期向主节点报告自己的偏移量。这两个偏移量用于判断主从之间的数据同步状态。当主从偏移量一致时,理论上它们的数据是同步的。
  3. 复制积压缓冲区 (Replication Backlog):主节点内部维护的一个固定大小的、环形的先进先出(FIFO)缓冲区。它存储了主节点最近产生的一部分写命令(即复制流的一部分)。当从节点因网络中断等原因与主节点短暂断开连接后,如果从节点记录的偏移量仍然存在于主节点的复制积压缓冲区内,那么主节点就可以直接从缓冲区中将从节点缺失的命令发送过去,实现部分重同步 (Partial Resynchronization),避免了成本高昂的全量同步 (Full Resynchronization)。缓冲区的大小可以通过 repl-backlog-size 配置项调整。
  4. PSYNC 命令:Redis 2.8 版本引入的新一代同步命令,取代了旧的 SYNC 命令。PSYNC 能够智能地处理全量同步和部分重同步。从节点启动复制时会向主节点发送 PSYNC <master_runid> <offset> 命令。
    • 如果 <master_runid>?<offset>-1,表示从节点是首次连接或不确定之前的主节点信息,请求进行全量同步。
    • 如果 <master_runid> 是从节点之前记录的主节点 Run ID,<offset> 是从节点当前的复制偏移量,表示从节点尝试进行部分重同步。

三、 主从复制的详细工作流程

Redis 主从复制的过程大致可以分为以下几个阶段:

阶段一:建立连接与协商 (Handshake)

  1. 设置主从关系
    • 可以通过在从节点的配置文件 redis.conf 中添加 replicaof <master_ip> <master_port> 指令(Redis 5 之前是 slaveof)。
    • 或者在从节点启动后,通过客户端执行 REPLICAOF <master_ip> <master_port> 命令(Redis 5 之前是 SLAVEOF)。
    • 执行 REPLICAOF no one 可以使从节点断开与主节点的复制关系,变回独立节点。
  2. 建立 Socket 连接:从节点根据配置或命令中的主节点 IP 和端口,主动与主节点建立 TCP 连接。如果连接成功,主节点会接受该连接。
  3. 发送 PING 命令:从节点向主节点发送一个 PING 命令,用于测试连接是否通畅以及主节点是否能正常响应。主节点应回复 PONG
  4. 身份验证 (可选):如果主节点设置了 requirepass 密码,从节点需要在配置文件或通过 MASTERAUTH <password> 命令提供正确的密码 (masterauth 配置项)。从节点会在后续的交互中发送 AUTH <password> 进行认证。
  5. 端口与能力协商
    • 从节点向主节点发送 REPLCONF listening-port <slave_listening_port>,告知主节点自己的监听端口。主节点在 INFO replication 输出中会显示从节点的端口信息。
    • 从节点可能还会发送 REPLCONF capa eofREPLCONF capa psync2 等命令,告知主节点自己支持的复制能力(例如,支持 RDB 文件传输结束标记、支持 PSYNC 2.0 协议等)。主节点会根据这些信息调整复制行为。

阶段二:数据同步 (Synchronization)

这是主从复制的核心阶段,根据情况可能进行全量同步或部分重同步。

  1. 尝试部分重同步 (PSYNC):从节点向主节点发送 PSYNC <master_runid> <offset> 命令。
    • <master_runid> 是从节点上次连接的主节点的 Run ID(如果是第一次连接,则为 ?)。
    • <offset> 是从节点当前的复制偏移量(如果是第一次连接,则为 -1)。
  2. 主节点响应 PSYNC:主节点收到 PSYNC 命令后,会根据情况做出响应:
    • 情况 A:执行全量同步 (Full Resynchronization)
      • 触发条件
        • 从节点是第一次连接主节点 (PSYNC ? -1)。
        • 从节点发送的 master_runid 与主节点当前的 Run ID 不匹配(说明主节点已重启或发生了故障转移)。
        • 从节点请求的 offset 超出了主节点复制积压缓冲区的范围(即从节点断线时间太长,丢失的命令已不在缓冲区内)。
      • 过程
        1. 主节点回复 +FULLRESYNC <master_runid> <initial_offset><master_runid> 是主节点当前的 Run ID,<initial_offset> 是主节点当前的复制偏移量。从节点需要记录这两个值。
        2. 主节点执行 BGSAVE 命令,在后台异步生成一个 RDB 快照文件。
        3. BGSAVE 执行期间,主节点会将所有新接收到的写命令缓存到内存的一个复制缓冲区中(注意,这不同于复制积压缓冲区,这个缓冲区是临时的,用于 RDB 生成期间的命令)。
        4. BGSAVE 完成后,主节点将生成的 RDB 文件发送给从节点。
        5. 从节点接收 RDB 文件。在接收期间,它可能会清空自己现有的所有数据(这是为了确保与主节点快照状态一致)。
        6. 从节点加载接收到的 RDB 文件,恢复数据到内存中。这个过程可能会阻塞从节点。
        7. RDB 文件发送完毕后,主节点开始将之前缓存的写命令(步骤 3 中缓存的)发送给从节点。
        8. 从节点接收并执行这些来自缓冲区的写命令,使得自己的数据状态追赶上主节点在生成 RDB 快照期间发生的变化。
        9. 全量同步完成。之后进入命令传播阶段。
    • 情况 B:执行部分重同步 (Partial Resynchronization)
      • 触发条件
        • 从节点之前连接过该主节点,并且发送的 master_runid 与主节点当前的 Run ID 匹配。
        • 从节点请求的 offset 仍然在主节点的复制积压缓冲区 (Replication Backlog) 内。
      • 过程
        1. 主节点检查条件满足后,回复 +CONTINUE
        2. 主节点直接从复制积压缓冲区中,找到从节点请求的 offset + 1 位置开始的命令,并将这部分缺失的命令流发送给从节点。
        3. 从节点接收并执行这些命令,更新自己的数据状态和复制偏移量。
        4. 部分重同步完成,比全量同步快得多,资源消耗也小得多。之后进入命令传播阶段。

阶段三:命令传播 (Command Propagation)

一旦初始同步(无论是全量还是部分)完成,主从节点就进入了持续的命令传播阶段,以保持数据接近实时同步。

  1. 主节点转发写命令:主节点每执行一个会修改数据的写命令(如 SET, DEL, LPUSH, ZADD 等),除了将命令结果返回给客户端外,还会将这个写命令异步地发送给所有连接的从节点。
  2. 从节点接收并执行:从节点接收到主节点发来的写命令后,会在自己的数据集中执行相同的命令,从而保持与主节点数据的一致性。
  3. 心跳机制与ACK:为了维持连接和监控同步状态:
    • 主节点会定期(默认每秒)向从节点发送 PING 命令(在命令流中表现为特殊标记,不是显式的 PING 命令),检查从节点是否存活。
    • 从节点会定期(默认每秒)向主节点发送 REPLCONF ACK <processed_offset> 命令,告知主节点自己已经处理到的复制偏移量。这个 ACK 有两个作用:
      • 让主节点了解从节点的同步进度。INFO replication 命令可以看到每个从节点的 lag(延迟的秒数,基于上次收到 ACK 的时间)。
      • 帮助主节点检测超时的从节点。如果主节点在配置的 repl-timeout 时间内(默认 60 秒)没有收到从节点的 ACK,会认为该从节点已下线,并断开连接。

四、 主从复制的特点与注意事项

  • 异步复制:Redis 的主从复制默认是异步进行的。主节点执行写命令后,会立即返回给客户端,然后才将命令异步发送给从节点。这意味着在主节点写入成功到从节点同步完成之间存在一个短暂的时间窗口(复制延迟 Replication Lag)。如果在这期间主节点宕机且没有被 Sentinel 及时切换,可能会丢失最后几条未能同步的写命令。
  • 复制延迟 (Replication Lag):网络延迟、主节点负载过高、从节点负载过高或执行慢命令等都可能导致复制延迟增大。监控复制延迟(通过 INFO replication 中的 lag 或 Sentinel 的信息)非常重要。
  • 全量同步的开销:全量同步是一个资源密集型操作。主节点的 BGSAVE 会消耗 CPU 和内存,如果内存不足可能导致 OOM;RDB 文件传输会占用网络带宽;从节点清空数据和加载 RDB 会消耗 CPU 和内存,并可能导致服务短暂中断(无法处理读请求)。应尽量避免频繁的全量同步,合理配置 repl-backlog-size 对此至关重要。
  • 主节点阻塞风险:如果主节点配置了 stop-writes-on-bgsave-error yes(默认),且 BGSAVE 失败,主节点会停止接受写操作以保护数据一致性。另外,如果连接的从节点数量过多,或者网络状况不佳导致复制缓冲区快速填满,也可能间接影响主节点性能。
  • 无盘复制 (Diskless Replication):为了避免 BGSAVE 产生的磁盘 I/O 开销,特别是对于磁盘性能较差的环境,Redis 提供了无盘复制 (repl-diskless-sync yes)。此时,主节点直接在内存中生成 RDB 数据流,并通过网络套接字直接发送给从节点,不写入本地磁盘。这会消耗更多内存,但可能更快。
  • 链式复制与树状复制:从节点可以配置为其他从节点的“主节点”,形成复制链(A -> B -> C)。这可以减轻顶级主节点(A)的复制压力,但会增加整体的复制延迟。不推荐过深的复制链。

五、 优缺点总结

优点

  1. 高可用性基础:是 Sentinel 和 Cluster 实现自动故障转移的前提。
  2. 读性能扩展:通过读写分离,显著提升应用的读并发能力。
  3. 数据安全性:提供了数据的热备份。

缺点

  1. 异步复制带来的数据一致性问题:存在数据丢失的风险(虽然概率较低)。
  2. 主节点写压力未分散:所有写操作仍需由主节点处理,主节点是写操作的瓶颈。
  3. 全量同步开销大:对主从节点的 CPU、内存、网络和磁盘(非无盘复制时)都有较大影响。
  4. 不具备自动故障转移能力:需要配合 Sentinel 或 Cluster 才能实现自动的主从切换。

六、 结论

Redis 主从复制是 Redis 实现数据冗余、读性能扩展和高可用性的核心技术。通过理解其基本概念(如 Run ID、偏移量、积压缓冲区)和详细的工作流程(握手、同步(全量/部分)、命令传播),开发者和运维人员可以更好地配置、管理和监控 Redis 实例,优化其性能,并为构建更健壮的 Redis 服务(如使用 Sentinel 或 Cluster)打下坚实的基础。虽然它存在异步复制的局限性和全量同步的开销,但其设计简洁、高效,在绝大多数场景下都能很好地满足需求。在使用时,应根据业务场景仔细考虑配置(特别是 repl-backlog-sizerepl-timeout),并做好监控,以确保系统的稳定运行。


发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部