# 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 ID
和Offset
,试图进行增量复制。 - 如果
Replication ID
不匹配,或者Offset
超出主节点的复制缓冲区,则触发全量复制。
# (2)全量复制(Full Sync)
当从节点是首次连接主节点或 Offset
失效时,会触发全量复制,流程如下:
主节点执行 RDB 快照:
- 主节点 fork 一个子进程执行
bgsave
,生成 RDB 文件。 - 在生成 RDB 期间,主节点会将所有写操作缓存在复制缓冲区(Replication Backlog)中。
- 主节点 fork 一个子进程执行
RDB 文件传输至从节点:
- RDB 传输完成后,从节点会清空原数据,载入新的 RDB 文件。
应用增量数据:
- 载入 RDB 后,从节点会继续应用
Replication Backlog
中存储的增量数据,以保证数据完整性。
- 载入 RDB 后,从节点会继续应用
问题:为什么 Redis 需要使用 RDB 进行同步?
- 直接传输 Key-Value 可能导致巨大的网络开销,而 RDB 是二进制格式,能压缩数据并减少传输时间。
- 采用 RDB 而非 AOF 是因为 AOF 文件体积大,重放速度慢,而 RDB 直接加载即可恢复数据状态。
# (3)增量复制(Partial Sync)
如果从节点曾经连接过主节点,并且 Replication Offset
仍然有效,则可进行增量复制,即只传输缺失的数据,而不进行全量同步:
- 从节点发送 Offset:从节点请求主节点同步从
Offset
之后的变更数据。 - 主节点检查 Replication Backlog:如果
Offset
仍在Replication Backlog
内,则直接从缓冲区发送增量数据。 - 从节点应用增量数据,避免全量复制带来的性能消耗。
增量复制的作用:
- 避免因网络抖动或短暂断线导致的全量复制开销。
- 仅传输必要的增量数据,提高同步效率。
- 通过
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 个从节点 在 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 模式如何进行数据迁移?