Redis 主从复制
主从复制(Replication)让一台主库把数据同步到若干从库:主库负责写,从库分担读,并作为故障切换的备用节点。它是哨兵高可用与集群方案的基石。
配置一个从库
从库只需知道“主库是谁”。在从库配置文件中写 replicaof(新写法,替代旧的 slaveof):
replicaof 192.168.1.10 6379 # 从库启动后自动跟随该主库
replica-read-only yes # 从库默认只读,防误写造成分叉
也可以运行时动态指定,立即生效:
127.0.0.1:6379> REPLICAOF 192.168.1.10 6379
# 输出:OK
127.0.0.1:6379> INFO replication
# 输出:# Replication
# role:slave
# master_host:192.168.1.10
# master_port:6379
# master_link_status:up
全量同步与增量同步
- 首次复制或断线太久:全量同步。从库发 PSYNC 携带自己的 replid 与偏移量,主库发现无法续传便 BGSAVE 生成 RDB 快照传给从库,从库清空本地后加载,再追赶积压的命令。
- 正常运行:增量同步。主库每执行一条写命令就实时转发给从库,同时写入复制积压缓冲区 repl backlog。
- 用 master_replid 标识数据流、master_repl_offset 标识复制进度,二者都在 INFO replication 中可查。
主库一侧可看到从库状态与复制偏移:
127.0.0.1:6379> INFO replication
# 输出:# Replication
# role:master
# connected_slaves:1
# slave0:ip=192.168.1.11,port=6379,state=online,offset=3521,lag=0
# master_repl_offset:3521
拓扑与读写分离
- 一主多从:一个主库挂多个从库,最常见的读扩展形态。
- 链式复制:从库 A 再挂从库 B(A→B),减轻主库分发连接的负担。
- 应用把读请求打到从库、写请求打到主库,就实现了读写分离。
从库默认只读,对从库执行写命令会报错:
127.0.0.1:6379> SET k 1
# 输出:(error) READONLY You can't write against a read only replica.
从库晋升为主
演练或主库故障时,让某从库脱离关系独立成主:
127.0.0.1:6379> REPLICAOF NO ONE
# 输出:OK
此后其他从库再 REPLICAOF 指向它即可。手工晋升是理解哨兵自动故障转移的基础。
延迟与常见坑
- 复制是异步的:主库写完即返回,从库可能有短暂滞后,强一致读不能依赖从库。
- 断线过久或 backlog 太小会退化成全量同步,瞬间压力大;可调大积压缓冲区扩大增量续传窗口:
repl-backlog-size 64mb # 默认 1mb,写频繁的实例建议调大
- 全量同步瞬间主库要 fork 子进程做 BGSAVE 并传输 RDB,注意内存与带宽余量。
- 复制≠持久化:主库若关闭持久化,从库可能被“空主库”全量同步清空,见持久化一章。
小结:主从复制提供“单写多读 + 数据冗余”,配置只需 replicaof 一行;写走主、读走从,并用 repl backlog 缓解断线重连。要自动切换主从,则交给下一章的哨兵。