外观
Redis 主从复制
Redis 主从复制是 Redis 高可用性架构的基础,通过主从复制可以实现数据的冗余备份、读写分离和负载均衡。本文档将详细介绍 Redis 主从复制的核心概念、工作原理、配置方法、管理和监控以及最佳实践。
主从复制原理
1. 复制的三个阶段
Redis 主从复制过程分为三个阶段:
1.1 连接建立阶段
- 从节点发起连接:从节点通过
SLAVEOF命令或配置文件指定主节点地址和端口 - 主从握手:从节点向主节点发送
SYNC命令,请求同步数据 - 建立复制关系:主节点接受从节点的连接请求,建立复制关系
1.2 数据同步阶段
- 主节点生成 RDB 文件:主节点执行
BGSAVE命令生成 RDB 文件 - 主节点发送 RDB 文件:主节点将生成的 RDB 文件发送给从节点
- 从节点加载 RDB 文件:从节点接收 RDB 文件并加载到内存中
- 主节点发送缓冲区命令:主节点将生成 RDB 文件期间的写命令发送给从节点
- 从节点执行缓冲区命令:从节点执行主节点发送的缓冲区命令,实现数据一致性
1.3 命令传播阶段
- 主节点发送写命令:主节点将后续的写命令实时发送给从节点
- 从节点执行写命令:从节点实时执行主节点发送的写命令,保持数据与主节点一致
- 心跳机制:主从节点之间通过心跳机制保持连接
2. 全量复制
全量复制是指从节点第一次连接主节点时,主节点将所有数据发送给从节点的过程。
2.1 全量复制触发条件
- 从节点第一次连接主节点
- 从节点与主节点的复制偏移量差距超过复制积压缓冲区大小
- 主节点重启后,从节点重新连接
2.2 全量复制过程
- 从节点向主节点发送
PSYNC ? -1命令,请求同步数据 - 主节点返回
FULLRESYNC <runid> <offset>命令,告知从节点需要执行全量复制 - 主节点执行
BGSAVE命令生成 RDB 文件 - 主节点将生成 RDB 文件期间的写命令存储到复制缓冲区
- 主节点将 RDB 文件发送给从节点
- 从节点接收并加载 RDB 文件
- 主节点将复制缓冲区中的写命令发送给从节点
- 从节点执行这些写命令,实现数据一致性
2.3 全量复制的影响
- 主节点开销:生成 RDB 文件和发送 RDB 文件会消耗主节点的 CPU、内存和网络资源
- 从节点开销:接收和加载 RDB 文件会消耗从节点的网络、内存和磁盘资源
- 复制延迟:全量复制过程中,从节点数据与主节点存在延迟
- 带宽消耗:大量从节点同时进行全量复制会消耗大量网络带宽
3. 部分复制
部分复制是指从节点与主节点断开连接后重新连接时,只复制断开期间主节点的写命令的过程。
3.1 部分复制触发条件
- 从节点与主节点的复制偏移量差距在复制积压缓冲区大小范围内
- 从节点重新连接主节点时,主节点的 runid 未发生变化
3.2 部分复制关键组件
- 复制偏移量:主节点和从节点各自维护一个复制偏移量,记录已复制的字节数
- 复制积压缓冲区:主节点维护的一个环形缓冲区,存储最近的写命令
- runid:每个 Redis 实例的唯一标识符,用于标识主节点身份
3.3 部分复制过程
- 从节点向主节点发送
PSYNC <runid> <offset>命令,请求部分复制 - 主节点检查 runid 和复制偏移量:
- 如果 runid 匹配且偏移量在复制积压缓冲区内,返回
CONTINUE,执行部分复制 - 否则,返回
FULLRESYNC <runid> <offset>,执行全量复制
- 如果 runid 匹配且偏移量在复制积压缓冲区内,返回
- 主节点从复制积压缓冲区中读取从节点缺失的写命令
- 主节点将这些写命令发送给从节点
- 从节点执行这些写命令,实现数据一致性
3.4 部分复制的优势
- 减少复制延迟:只复制断开期间的写命令,减少复制时间
- 降低主节点开销:不需要生成和发送 RDB 文件
- 减少网络带宽消耗:只传输断开期间的写命令
- 提高复制效率:适用于网络不稳定的场景
4. 心跳机制
主从节点之间通过心跳机制保持连接,监控对方状态。
- 主节点心跳:主节点每隔 10 秒向从节点发送
PING命令 - 从节点心跳:从节点每隔 1 秒向主节点发送
REPLCONF ACK <offset>命令,包含当前复制偏移量 - 心跳作用:
- 检测主从节点之间的网络连接状态
- 主节点通过从节点的 ACK 命令了解从节点的复制进度
- 从节点通过主节点的 PING 命令了解主节点的状态
主从复制配置
1. 配置主节点
主节点默认不需要特殊配置,只需确保以下配置正确:
txt
# redis.conf
# 监听地址,建议绑定到特定IP
bind 0.0.0.0
# 端口号
port 6379
# 开启保护模式
protected-mode yes
# 设置密码(可选)
requirepass your_password
# 复制积压缓冲区大小(默认1mb)
repl-backlog-size 1mb
# 复制积压缓冲区过期时间(默认3600秒)
repl-backlog-ttl 36002. 配置从节点
从节点需要配置主节点的地址和端口,可以通过配置文件或命令方式配置。
2.1 配置文件方式
txt
# redis.conf
# 监听地址
bind 0.0.0.0
# 端口号
port 6380
# 开启保护模式
protected-mode yes
# 配置主节点地址和端口
replicaof 127.0.0.1 6379
# 配置主节点密码
masterauth your_password
# 从节点只读模式(默认yes)
replica-read-only yes
# 启用无盘复制(默认no)
repl-diskless-sync no
# 无盘复制延迟时间(默认5秒)
repl-diskless-sync-delay 5
# 从节点优先级(默认100)
replica-priority 1002.2 命令方式
bash
# 连接从节点
redis-cli -p 6380
# 配置主节点
127.0.0.1:6380> SLAVEOF 127.0.0.1 6379
# 配置主节点密码
127.0.0.1:6380> CONFIG SET masterauth your_password
# 查看复制状态
127.0.0.1:6380> INFO replication2.3 取消复制关系
bash
# 连接从节点
redis-cli -p 6380
# 取消复制关系
127.0.0.1:6380> SLAVEOF NO ONE3. 验证复制状态
使用 INFO replication 命令可以查看主从复制状态:
3.1 主节点复制状态
bash
redis-cli -p 6379 info replication输出示例:
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6380,state=online,offset=1000,lag=0
slave1:ip=127.0.0.1,port=6381,state=online,offset=1000,lag=0
master_replid:5337f03d7d9a8c9a900c8912b893594a08bc71f0
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:1000
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:10003.2 从节点复制状态
bash
redis-cli -p 6380 info replication输出示例:
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:1000
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:5337f03d7d9a8c9a900c8912b893594a08bc71f0
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:1000
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:1000主从复制管理
1. 查看复制状态
使用 INFO replication 命令查看主从复制状态,重点关注以下指标:
- master_link_status:从节点与主节点的连接状态(up/down)
- slave_repl_offset:从节点的复制偏移量
- master_repl_offset:主节点的复制偏移量
- lag:从节点与主节点的复制延迟(秒)
- connected_slaves:主节点连接的从节点数量
2. 从节点只读模式
从 Redis 2.6 开始,从节点默认处于只读模式,可以通过以下配置修改:
txt
# redis.conf
replica-read-only yes或通过命令方式:
bash
redis-cli -p 6380 CONFIG SET replica-read-only no3. 从节点故障处理
- 检测故障:通过监控
master_link_status指标检测从节点故障 - 处理故障:
- 如果从节点暂时不可用,等待其恢复后自动重连
- 如果从节点永久故障,移除该从节点并添加新的从节点
- 数据一致性:从节点恢复后,会自动与主节点同步数据
4. 主节点故障处理
- 检测故障:通过监控主节点的心跳或使用 Sentinel 检测主节点故障
- 手动故障转移:
- 选择一个健康的从节点
- 执行
SLAVEOF NO ONE命令将其提升为主节点 - 其他从节点执行
SLAVEOF new-master-ip new-master-port命令连接新主节点
- 自动故障转移:使用 Redis Sentinel 实现自动故障转移
5. 更换主节点
在某些情况下,需要更换主节点,例如主节点硬件升级、迁移等:
- 选择新主节点:选择一个健康的从节点作为新主节点
- 执行手动故障转移:
- 在新主节点上执行
SLAVEOF NO ONE - 在其他从节点上执行
SLAVEOF new-master-ip new-master-port
- 在新主节点上执行
- 更新客户端配置:将客户端连接指向新主节点
- 监控新主节点状态:确保新主节点正常运行,从节点同步正常
主从复制监控
1. 监控指标
复制状态:
master_link_status:从节点与主节点的连接状态connected_slaves:主节点连接的从节点数量slave_repl_offset:从节点的复制偏移量master_repl_offset:主节点的复制偏移量lag:从节点与主节点的复制延迟
复制性能:
repl_backlog_active:复制积压缓冲区是否激活repl_backlog_size:复制积压缓冲区大小repl_backlog_histlen:复制积压缓冲区中当前存储的字节数repl_backlog_first_byte_offset:复制积压缓冲区中第一个字节的偏移量
持久化相关:
rdb_last_bgsave_status:最后一次 BGSAVE 命令的执行状态rdb_last_bgsave_time_sec:最后一次 BGSAVE 命令的执行时间aof_last_bgrewrite_status:最后一次 AOF 重写命令的执行状态
2. 监控工具
Redis 内置命令:
INFO replication:查看复制状态MONITOR:实时监控 Redis 命令执行CLIENT LIST:查看客户端连接信息
第三方监控工具:
- Prometheus + Grafana:常用的监控组合,支持自定义仪表盘
- Redis Exporter:用于采集 Redis 监控指标
- Datadog:提供 Redis 监控集成
- New Relic:提供 Redis 监控集成
- Zabbix:支持 Redis 监控模板
3. 常见问题
3.1 从节点与主节点连接断开
- 原因:网络故障、主节点故障、配置错误等
- 检测:监控
master_link_status指标 - 处理:检查网络连接、主节点状态、配置文件等
3.2 复制延迟过大
原因:
- 主节点写入量过大
- 从节点性能不足
- 网络带宽不足
- 全量复制正在进行
- 从节点执行了慢查询
处理:
- 优化主节点写入性能
- 提升从节点硬件配置
- 增加网络带宽
- 合理配置复制积压缓冲区大小
- 避免在从节点执行慢查询
3.3 从节点频繁进行全量复制
原因:
- 主节点频繁重启
- 从节点与主节点的复制偏移量差距超过复制积压缓冲区大小
- 主节点的 runid 发生变化
处理:
- 减少主节点重启次数
- 增加复制积压缓冲区大小
- 确保从节点与主节点的网络连接稳定
主从复制最佳实践
1. 部署建议
- 主从节点分布:将主节点和从节点部署在不同的物理机器或可用区,避免单点故障
- 从节点数量:根据业务需求和主节点性能确定从节点数量,一般建议 2-5 个
- 级联复制:对于大量从节点的场景,使用级联复制减少主节点的复制压力
- 硬件配置:主节点和从节点使用相同或相似的硬件配置,确保从节点能够处理主节点的写负载
2. 配置优化
- 复制积压缓冲区:根据主节点的写入量调整
repl-backlog-size,建议设置为平均写入量的 2-3 倍 - 无盘复制:对于网络带宽充足、磁盘 IO 紧张的场景,启用无盘复制(
repl-diskless-sync yes) - 从节点优先级:根据从节点性能设置不同的
replica-priority,确保故障转移时选择最优从节点 - 持久化配置:主节点启用 AOF 持久化,确保数据安全;从节点可以禁用持久化或使用不同的持久化策略
- 内存配置:主节点和从节点配置足够的内存,避免内存溢出
3. 监控与告警
- 建立完善的监控体系:监控主从复制状态、复制延迟、网络连接等指标
- 设置合理的告警阈值:
- 复制延迟超过 10 秒告警
- 从节点与主节点连接断开告警
- 主节点连接的从节点数量异常告警
- 定期检查:定期检查主从复制状态,确保数据一致性
- 记录日志:开启 Redis 日志,便于分析问题
4. 故障处理
- 制定故障转移计划:提前制定手动和自动故障转移计划
- 定期测试故障转移:模拟主节点故障,测试故障转移流程
- 备份数据:定期备份主节点数据,确保数据安全
- 恢复演练:定期进行数据恢复演练,确保能够快速恢复数据
5. 性能优化
- 读写分离:将读取请求分散到从节点,减轻主节点压力
- 连接池:使用连接池管理客户端连接,减少连接开销
- 合理使用管道:使用管道(Pipeline)减少网络往返次数
- 避免慢查询:在从节点避免执行慢查询,如
KEYS *、SORT等 - 优化主节点写入:减少大键写入,优化数据结构
常见问题(FAQ)
Q1: 主从复制如何保证数据一致性?
A1: Redis 主从复制通过以下机制保证数据一致性:
- 命令传播:主节点将写命令实时发送给从节点
- 复制偏移量:主从节点通过复制偏移量确保数据同步进度
- 复制积压缓冲区:用于部分复制,确保断开连接后的数据一致性
- 心跳机制:监控主从节点连接状态
- 持久化:主节点启用持久化,确保数据不丢失
Q2: 主从复制会影响主节点性能吗?
A2: 主从复制会对主节点产生一定的性能影响:
- CPU 开销:生成 RDB 文件、处理从节点请求
- 内存开销:维护复制积压缓冲区、复制缓冲区
- 网络开销:发送 RDB 文件和写命令给从节点
- 磁盘开销:生成 RDB 文件
可以通过以下方式减少影响:
- 合理配置从节点数量
- 使用级联复制
- 启用无盘复制
- 优化网络带宽
Q3: 从节点可以有自己的从节点吗?
A3: 是的,Redis 支持级联复制,从节点可以作为其他从节点的主节点,形成链式或树状复制结构。这种方式可以减少主节点的复制压力,适用于大量从节点的场景。
Q4: 如何选择合适的从节点优先级?
A4: 从节点优先级(replica-priority)用于故障转移时选择新主节点,优先级值越小,优先级越高。选择合适的从节点优先级需要考虑:
- 从节点性能:性能更好的从节点优先级更高
- 复制延迟:复制延迟更小的从节点优先级更高
- 硬件配置:硬件配置更好的从节点优先级更高
- 网络位置:网络更稳定的从节点优先级更高
Q5: 主从复制与 Redis Cluster 有什么区别?
A5: 主从复制和 Redis Cluster 是 Redis 两种不同的高可用解决方案:
主从复制:
- 适用于中小规模 Redis 部署
- 提供数据冗余和读写分离
- 不支持数据分片
- 需要手动或使用 Sentinel 实现故障转移
Redis Cluster:
- 适用于大规模 Redis 部署
- 提供数据分片、高可用性和自动故障转移
- 支持水平扩展
- 内置故障检测和自动故障转移功能
Q6: 如何监控主从复制延迟?
A6: 监控主从复制延迟的方法:
- 使用 INFO replication 命令:查看
lag指标 - 监控复制偏移量:比较主节点和从节点的
master_repl_offset和slave_repl_offset - 使用监控工具:Prometheus + Grafana、Datadog 等提供复制延迟监控
- 自定义脚本:编写脚本定期检查复制延迟
