# 17. Redis 主从复制的工作原理是什么?如何保证主从数据一致性?

# 标准答案

Redis 主从复制(Replication)是一种异步数据同步机制,主节点(Master)会将数据变更异步地复制到从节点(Slave),以提高数据可用性和读性能。复制流程包括连接建立、全量同步(Full Sync)、增量同步(Partial Sync)和心跳检测

Redis 采用 PSYNC2 协议 来优化复制过程,并使用 复制偏移量(Replication Offset)、复制缓冲区(Replication Backlog)和ACK确认机制 来保证数据一致性。当主节点故障时,从节点可通过 Sentinel 机制 选举新的主节点,但可能存在一定的数据丢失风险。

# 答案解析

Redis 主从复制的核心目标是:在多台 Redis 服务器间复制数据,提升读负载能力,保障数据可用性,并在主节点故障时快速恢复服务。其核心机制围绕 数据同步数据一致性 展开。

# 1️⃣ Redis 主从复制的核心流程

主从复制的基本流程如下:

# (1)从节点连接主节点,发起复制请求

  • 当从节点启动时,会向主节点发送 PSYNC ? -1 请求。
  • 如果从节点曾经连接过该主节点,会携带上次的 Replication IDOffset,试图进行增量复制。
  • 如果 Replication ID 不匹配,或者 Offset 超出主节点的复制缓冲区,则触发全量复制。

# (2)全量复制(Full Sync)

当从节点是首次连接主节点或 Offset 失效时,会触发全量复制,流程如下:

  1. 主节点执行 RDB 快照

    • 主节点 fork 一个子进程执行 bgsave,生成 RDB 文件。
    • 在生成 RDB 期间,主节点会将所有写操作缓存在复制缓冲区(Replication Backlog)中。
  2. RDB 文件传输至从节点

    • RDB 传输完成后,从节点会清空原数据,载入新的 RDB 文件。
  3. 应用增量数据

    • 载入 RDB 后,从节点会继续应用 Replication Backlog 中存储的增量数据,以保证数据完整性。

问题:为什么 Redis 需要使用 RDB 进行同步?

  • 直接传输 Key-Value 可能导致巨大的网络开销,而 RDB 是二进制格式,能压缩数据并减少传输时间。
  • 采用 RDB 而非 AOF 是因为 AOF 文件体积大,重放速度慢,而 RDB 直接加载即可恢复数据状态。

# (3)增量复制(Partial Sync)

如果从节点曾经连接过主节点,并且 Replication Offset 仍然有效,则可进行增量复制,即只传输缺失的数据,而不进行全量同步:

  1. 从节点发送 Offset:从节点请求主节点同步从 Offset 之后的变更数据。
  2. 主节点检查 Replication Backlog:如果 Offset 仍在 Replication Backlog 内,则直接从缓冲区发送增量数据。
  3. 从节点应用增量数据,避免全量复制带来的性能消耗。

增量复制的作用

  • 避免因网络抖动或短暂断线导致的全量复制开销
  • 仅传输必要的增量数据,提高同步效率。
  • 通过 Replication Backlog 机制,保持主从数据的一致性。

# (4)主从同步中的 ACK 机制

Redis 的主从同步不是完全异步的,而是半异步,其中包含 ACK 确认机制,保证数据传输完整性:

  • 主节点在复制数据时,会维护 Replication Offset,表示已发送的数据量。
  • 从节点在接收到数据后,会定期向主节点发送 ACK 确认,报告自己的 Offset
  • 主节点会对比从节点 Offset,如果滞后过多,则可能降低同步速度,确保从节点不会崩溃。

ACK 机制在网络波动、主从负载不均衡时,能够有效减少数据丢失风险。

# 2️⃣ Redis 如何保证主从数据一致性?

# (1)Replication Offset & Replication Backlog

Redis 采用 Replication Offset(复制偏移量)Replication Backlog(复制缓冲区) 机制保证数据一致性。

  • Replication Offset:主从节点都维护自己的 Offset,主节点的 Offset 代表已经写入的数据量,从节点的 Offset 代表已经同步的数据量。
  • Replication Backlog:主节点会存储最近的变更数据(默认1MB),当从节点断开后重连时,若 Offset 仍在缓冲区范围内,则可进行增量同步,避免全量复制。

# (2)PSYNC2 协议(复制 ID 机制)

Redis 4.0 引入 PSYNC2 协议,用来提高主从同步的稳定性。

  • 每个主节点都有一个 Replication ID,当主节点切换时,会生成新的 Replication ID,从节点可以通过 Replication ID 确定数据来源。
  • 旧的 Replication ID 仍然保留,从节点可用于回溯历史数据,减少数据丢失风险。

# (3)WAIT 机制

由于 Redis 主从复制是异步的,可能导致主节点写入的数据未同步到从节点即发生故障,导致数据丢失。为了提高一致性,Redis 提供 WAIT 命令:

WAIT 1 500
1

含义:等待至少 1 个从节点500 毫秒内 确认数据复制成功,否则返回失败。

  • WAIT 提高了数据一致性,但会带来写入延迟,适用于对一致性要求高的业务。
  • WAIT 只能保证主从一致性,但不能防止脑裂问题(需要 min-slaves-to-write 结合使用)。

# 3️⃣ Redis 主从复制的缺陷与一致性挑战

主从复制默认是异步的,可能造成数据丢失

  • 主节点崩溃后,从节点可能没有收到最新数据,导致数据丢失。

全量复制成本高

  • RDB 快照和数据同步会增加 CPU 和 I/O 负担,影响主节点性能。

主从切换可能导致脑裂

  • 在网络分区情况下,主从可能产生不同的数据副本,导致不一致。

# 深入追问

🔹 如何优化 Redis 复制,减少全量复制的发生?
🔹 Redis 复制的 ACK 机制如何保证数据不会丢失?
🔹 如何在 Redis Sentinel 下实现高可用切换,保证数据一致性?
🔹 在 Redis Cluster 模式下,如何保证分片之间的数据同步?

# 相关面试题

🔹 Redis Sentinel 如何进行主从切换?
🔹 Redis 主从复制的网络分区问题如何解决?
🔹 Redis 的 min-slaves-to-write 作用是什么?
🔹 Redis Cluster 模式如何进行数据迁移?