Redis 主从同步原理¶
一、为什么需要主从¶
- 读写分离:主写从读,分担压力。
- 高可用:主挂了,从可以晋升为主(Sentinel / Cluster)。
- 数据冗余:多副本,不怕单节点故障。
二、全量同步(第一次连接)¶
从库第一次连接主库,主库不能直接发当前数据,因为从库要边收边追。流程:
- 从库发送
PSYNC ? -1(第一次不知道主库 runid)。 - 主库返回
+FULLRESYNC <runid> <offset>,表示要全量同步。 - 主库执行
BGSAVE生成 RDB 快照(fork 子进程)。 - RDB 生成期间,新写命令写入 replication buffer(复制缓冲区)。
- RDB 发给从库,从库加载。
- 主库把 buffer 期间的写命令发给从库,从库重放。
完成后,进入增量同步阶段。
三、增量同步(断线重连)¶
网络抖动导致主从中断,重连后:
- 从库发送
PSYNC <runid> <offset>,告诉主库"我同步到这个偏移量了"。 - 主库判断:
- runid 匹配,且 offset 在复制积压缓冲区(repl_backlog)内:只发缺失部分。
- 不在缓冲区:只能做全量同步。
repl_backlog_size 默认 1MB,网络抖动久了就可能被覆盖,被迫全量。
四、命令传播(持续同步)¶
全量完成后,主库每执行一个写命令,就异步把命令发给所有从库。
从库默认只读(replica-read-only yes)。
五、心跳与超时¶
- 从库每秒发送
REPLCONF ACK <offset>,汇报同步进度。 - 主库
repl-ping-replica-period检查从库是否存活。 repl-timeout超时则断开重连。
六、主从延迟¶
原因:
- 主库写、从库重放是异步的。
- 从库机器性能差、网络抖动。
- 大 key 同步阻塞从库。
解决:
- 监控
master_repl_offset与slave_repl_offset差。 - 关键读走主库(或强制读主逻辑)。
- 避免大 key。
七、Sentinel 与 Cluster¶
Sentinel(哨兵)¶
- 监控主从节点。
- 主挂了自动选一个从晋升为主。
- 客户端通过 Sentinel 发现主节点地址。
Cluster¶
- 数据按 16384 个槽分布在多个主节点。
- 每个主节点有从节点。
- 去中心化,Gossip 协议通信。
高频追问
- Redis 为什么不用 Paxos / Raft?主从复制是异步的,所以不能强一致;Sentinel 选主用 Raft 思想。
- 复制积压缓冲区(repl_backlog)是环形缓冲区,主库所有从库共享,不是每个从库一份。