Redis集群主从复制与一致性
Redis集群通过主从复制实现数据冗余和高可用,理解复制机制与一致性保证对集群运维至关重要。
主从复制原理
复制架构
Bash
主节点(Master):接收写请求,同步数据到从节点
从节点(Replica):接收读请求,复制主节点数据
复制流程
Bash
1. 从节点发送PSYNC请求
2. 主节点执行BGSAVE生成RDB
3. 主节点发送RDB给从节点
4. 从节点加载RDB
5. 主节点发送增量命令
6. 进入持续同步状态
复制ID
Bash
每个主节点有两个复制ID:
- master_replid: 当前复制ID
- master_replid2: 前任复制ID(用于部分重同步)
复制偏移量:
- master_repl_offset: 主节点偏移量
- slave_repl_offset: 从节点偏移量
复制类型
全量同步
Bash
触发条件:
1. 从节点首次连接
2. 从节点复制偏移量不在主节点缓冲区
3. 主从复制ID不匹配
流程:
1. 主节点BGSAVE
2. 生成RDB文件
3. 发送到从节点
4. 从节点加载RDB
部分重同步
Bash
触发条件:
1. 主从复制ID匹配
2. 复制偏移量在缓冲区内
流程:
1. 从节点发送PSYNC {replid} {offset}
2. 主节点检查复制ID和偏移量
3. 主节点发送offset之后的命令
4. 从节点执行命令
增量同步
Bash
触发条件:
1. 部分重同步失败
2. 复制断开后重连
3. 积压缓冲区不足
流程:
1. 主节点维护积压缓冲区
2. 记录最近的写命令
3. 从节点请求缺失命令
复制配置
主节点配置
Bash
# 复制积压缓冲区大小
repl-backlog-size 1mb
# 积压缓冲区生存时间
repl-backlog-ttl 3600
# 复制超时
repl-timeout 60
# 禁用TCP_NODELAY(启用Nagle算法)
repl-disable-tcp-nodelay no
# 从节点优先级
replica-priority 100
从节点配置
Python
# 设置主节点
replicaof 192.168.1.100 6379
# 只读模式(默认开启)
replica-read-only yes
# 从节点写策略
replica-serve-stale-data yes
# 复制确认
repl-diskless-sync no
集群从节点配置
Bash
# 集群模式下从节点配置
cluster-enabled yes
cluster-replica-validity-factor 10
cluster-migration-barrier 1
复制监控
INFO REPLICATION
Bash
INFO REPLICATION
# 输出示例
role:master
connected_slaves:2
slave0:ip=192.168.1.101,port=6379,state=online,offset=1000,lag=0
slave1:ip=192.168.1.102,port=6379,state=online,offset=1000,lag=1
master_replid:abc123...
master_repl_offset:1000
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:1000
关键指标
Bash
connected_slaves: 已连接从节点数
slave_repl_offset: 从节点复制偏移量
lag: 从节点延迟(秒)
repl_backlog_histlen: 积压缓冲区长度
复制延迟监控
Bash
# 查看复制延迟
redis-cli -h <master_ip> -p <master_port> INFO REPLICATION | grep lag
# 延迟告警条件
lag > 10秒:警告
lag > 60秒:严重
一致性问题
异步复制的风险
Bash
写入流程:
1. 客户端写入主节点
2. 主节点返回成功
3. 主节点异步复制到从节点
风险:
- 主节点故障时,从节点可能丢失未同步数据
- 读从节点可能读到旧数据
数据丢失窗口
Bash
丢失数据量 = 主节点偏移量 - 从节点偏移量
减少丢失:
1. 增大repl-backlog-size
2. 减小repl-timeout
3. 使用WAIT命令确认
WAIT命令
text
# 等待N个从节点确认同步
WAIT <numslaves> <timeout>
# 示例:等待2个从节点,超时100ms
SET key value
WAIT 2 100
# 返回:确认的从节点数
WAIT命令可减少数据丢失风险,但会降低写入性能。
一致性解决方案
读一致性策略
| 策略 | 实现 | 一致性 | 性能 |
|---|---|---|---|
| 读主节点 | 所有读请求发主节点 | 强一致 | 低 |
| 读从节点 | 读请求发从节点 | 最终一致 | 高 |
| 混合读取 | 写后读主,其他读从 | 会话一致 | 中 |
会话一致性
text
# 写入后短暂读主节点
SET key value
# 等待复制
WAIT 1 100
# 后续可读从节点
客户端实现
text
# 伪代码示例
def read_after_write(key):
# 写入主节点
master.set(key, value)
# 等待复制
master.wait(1, 100)
# 短时间内读主节点
return master.get(key)
集群读写分离
读写分离配置
text
# 从节点可读
replica-read-only yes
# 集群模式从节点可读(默认不可读)
# 需要在连接时指定READONLY
READONLY
客户端读写分离
text
# 集群模式默认所有请求路由到主节点
# 开启从节点读取需要:
# 1. 发送READONLY命令
# 2. 使用支持读写分离的客户端
读写分离风险
text
1. 读到旧数据(复制延迟)
2. 从节点故障时请求失败
3. 客户端路由复杂度增加
4. 主从切换期间读取异常
复制优化
无盘复制
text
# 主节点直接通过网络发送RDB
# 不落盘,适合磁盘慢、网络快的场景
repl-diskless-sync yes
repl-diskless-sync-delay 5
复制积压缓冲区优化
text
# 根据写入量和网络延迟调整
repl-backlog-size 100mb
# 计算公式
# backlog_size = 写入速度(MB/s) * 网络延迟(s) * 2
网络优化
text
# 禁用Nagle算法,减少延迟
repl-disable-tcp-nodelay no
# 增大复制超时时间
repl-timeout 120
主从切换影响
切换流程
text
1. 检测主节点故障
2. 从节点发起选举
3. 获胜从节点晋升
4. 更新集群配置
5. 客户端路由更新
数据同步
text
新主节点就绪后:
1. 其他从节点重新复制
2. 执行PSYNC请求
3. 可能全量或部分同步
4. 恢复复制状态
减少影响
text
# 提高故障检测速度
cluster-node-timeout 5000
# 保持足够从节点
cluster-migration-barrier 1
# 从节点预热
# 确保从节点数据尽量新
要点总结
- 复制类型:全量同步、部分重同步、增量同步
- 复制ID和偏移量决定同步类型
- 使用WAIT命令减少数据丢失风险
- 异步复制存在数据丢失窗口,读从节点可能读到旧数据
- repl-backlog-size影响部分重同步成功率
- 读写分离需要权衡一致性与性能
- 集群模式默认读主节点,READONLY开启从节点读取
- 监控复制延迟(lag)确保集群健康
📝 发现内容有误?点击此处直接编辑