主从复制与 Sentinel 高可用
主从复制解决“数据有副本”和“读取可分担”;Sentinel 解决“主节点不可用时谁来切换”。它们仍只有一个主节点处理写入,不能解决单机容量上限。
完成本章后,你应该能解释主节点失联后副本如何追赶数据、为什么 Sentinel 至少部署 3 个,以及应用为什么不能写死主节点 IP。
1. 先看清拓扑
┌→ replica-1(默认只读)
应用 → master(写)┤
└→ replica-2(默认只读)
sentinel-1 ┐
sentinel-2 ├→ 监控 master/replica,并对故障切换投票
sentinel-3 ┘
复制默认是异步的:主节点向客户端返回成功时,写入可能尚未到达副本。因此主机突然损坏时仍可能丢失最近写入。WAIT 能等待副本确认,但它不是强一致事务,不能消除所有故障窗口。
2. 全量同步和增量同步
- 副本向主节点发送
PSYNC; - 没有共同复制历史时,主节点执行全量同步;
- 主节点生成 RDB,同时缓冲生成期间的新写入;
- 副本加载 RDB,再执行缓冲命令;
- 后续持续接收命令流;
- 短暂断线后,如果 backlog 仍包含缺失 offset,则增量同步,否则再次全量同步。
# 副本 redis.conf
replicaof 10.0.10.11 6379
masteruser replication
masterauth 替换为复制密码
replica-read-only yes
repl-backlog-size 256mb
repl-diskless-sync yes
redis-cli -h 10.0.10.11 INFO replication
redis-cli -h 10.0.10.12 ROLE
| 字段 | 正常期望 |
|---|---|
role | 主节点 master,副本 slave/replica |
master_link_status | 副本为 up |
master_last_io_seconds_ago | 持续较小 |
| 主/副本 repl offset | 差距较小并能追平 |
repl_backlog_size | 覆盖常见网络中断窗口 |
backlog 可按“峰值写入字节率 × 可容忍断链时间 + 余量”估算。全量同步频繁时检查认证、网络、磁盘、大 key、副本输出缓冲和副本是否反复重启。
3. 动手搭建主从实验
docker network create redis-ha
docker run --detach --name redis-master --network redis-ha \
redis:7.4-alpine redis-server --appendonly yes
docker run --detach --name redis-replica-1 --network redis-ha \
redis:7.4-alpine redis-server --replicaof redis-master 6379
docker run --detach --name redis-replica-2 --network redis-ha \
redis:7.4-alpine redis-server --replicaof redis-master 6379
docker exec redis-master redis-cli SET ha:test 'from-master'
docker exec redis-replica-1 redis-cli GET ha:test
docker exec redis-replica-2 redis-cli INFO replication
尝试写副本:
docker exec redis-replica-1 redis-cli SET ha:test wrong-place
预期返回 READONLY。业务若读取副本,必须接受复制延迟导致的旧数据,并设计故障切换后的连接刷新。
4. Sentinel 如何判定和切换
- SDOWN:单个 Sentinel 主观认为实例不可达;
- ODOWN:达到 quorum 的 Sentinel 都认为主节点不可达;
- leader:本轮负责执行 failover 的 Sentinel;
- quorum:判定 ODOWN 的票数,不等于 leader 选举所需多数票。
至少部署 3 个 Sentinel,并跨故障域放置:
# sentinel.conf
port 26379
sentinel monitor mymaster 10.0.10.11 6379 2
sentinel auth-user mymaster sentinel
sentinel auth-pass mymaster 替换为密码
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1
redis-cli -p 26379 SENTINEL master mymaster
redis-cli -p 26379 SENTINEL replicas mymaster
redis-cli -p 26379 SENTINEL sentinels mymaster
redis-cli -p 26379 SENTINEL get-master-addr-by-name mymaster
Sentinel 配置文件必须可写,因为它会保存发现的节点和切换结果。容器中把 sentinel.conf 只读挂载,会导致状态无法持久保存。
5. 故障演练步骤
- 查询并记录当前主地址;
- 从应用侧持续执行测试写入;
- 停止主节点并开始计时;
- 观察
+sdown、+odown、+elected-leader、+switch-master日志; - 再查询主地址,确认已变化;
- 验证应用通过 Sentinel 发现新主并恢复写入;
- 恢复旧主,确认它成为新主的副本;
- 核对切换窗口的数据丢失或重复。
Sentinel 不切换的常见原因
- 可通信 Sentinel 数量不足或 quorum 不合理;
- Sentinel 与 Redis 的 ACL/密码配置错误;
- 26379 或 Redis 端口被防火墙阻断;
- 所有 Sentinel 与 Redis 位于同一故障主机;
- 应用写死旧主地址,实际已切换但应用仍报错。
6. 清理实验
docker rm --force redis-master redis-replica-1 redis-replica-2
docker network rm redis-ha