Redis设计与实现——分布式Redis
Redis Sentinel(哨兵)
Sentinel 的工作机制
-
故障检测(Failure Detection)
-
主观下线(Subjective Down):单个 Sentinel 实例检测到主节点在30 秒内无响应,标记其为
SDOWN
。 -
客观下线(Objective Down):当超过
quorum
的 Sentinel 实例确认主节点不可达,标记为ODOWN
,触发故障转移。
-
-
领导者选举(Leader Election)
-
Raft 算法:Sentinel 使用类似 Raft 的算法选举领头 Sentinel(Leader),由 Leader 执行故障转移。
-
选举条件:获得多数 Sentinel 实例的投票(
> N/2 + 1
,N 为 Sentinel 总数);避免多个 Sentinel 同时发起故障转移。
-
-
故障转移(Failover)流程
-
选择新主节点:Leader Sentinel 根据规则从从节点中选出新主节点:
优先级(
slave-priority
配置);复制偏移量最大(数据最新);运行 ID 字典序最小(最终裁决条件)。 -
提升新主节点:向目标从节点发送
SLAVEOF NO ONE
,使其成为主节点;等待新主节点确认角色切换。 -
切换从节点复制关系:向其他从节点发送
SLAVEOF
命令,使其复制新主节点。 -
更新配置:Sentinel 更新监控的主节点地址,并通知客户端。
-
-
客户端服务发现
-
连接流程:客户端向 Sentinel 查询当前主节点地址;客户端直接连接主节点,失败时重试查询。
-
SDK 支持:主流 Redis 客户端库(如 Jedis、Lettuce)内置 Sentinel 集成。
-
Sentinel 的架构与部署
-
Sentinel 部署模式
-
推荐配置:至少部署 3 个 Sentinel 实例(奇数个,避免脑裂),分布在独立物理节点。
-
网络拓扑:Sentinel 实例与 Redis 节点部署在同一网络,避免分区误判;Sentinel 之间通过 Gossip 协议通信,共享节点状态。
-
-
Sentinel 与 Redis 节点的关系
-
监控对象:每个 Sentinel 监控 一个主节点及其所有从节点。
-
自动发现:Sentinel 通过主节点获取从节点列表,并持续监控其状态。
-
Sentinel 的优缺点
-
优点
-
自动化容灾:无需人工干预即可完成故障转移。
-
高可用:Sentinel 自身多实例部署,避免单点故障。
-
客户端透明:客户端通过 Sentinel 自动发现主节点,业务代码无需硬编码地址。
-
-
缺点
-
数据一致性:异步复制可能导致故障转移后数据丢失(已提交但未同步到从节点的数据)。
-
复杂度:需部署多个 Sentinel 实例,配置和维护成本较高。
-
脑裂风险:网络分区可能导致多个主节点并存(需合理配置
quorum
和节点分布)。
-
生产环境建议
-
部署最佳实践
-
Sentinel 数量:至少 3 个实例,部署在独立物理节点或可用区。
-
网络优化:确保 Sentinel 与 Redis 节点间低延迟通信,避免跨地域部署。
-
监控告警:监控 Sentinel 日志和
INFO Sentinel
输出,关注odown
事件和故障转移次数。
-
-
避免脑裂的配置
-
合理设置quorum:通常设为
N/2 + 1
(N 为 Sentinel 总数)。 -
调整min-slaves-to-write:主节点需至少同步到指定数量的从节点才接受写操作。
-
-
客户端容错
-
重试策略:客户端应实现重试逻辑,处理故障转移期间的短暂不可用。
-
多语言 SDK:选择支持 Sentinel 的客户端库(如 Java 的 Jedis、Python 的 redis-py)。
-
常用命令
- SENTINEL masters:查看主节点信息。
- SENTINEL slaves {master}:查看从节点信息。
- SENTINEL failover {master}:强制触发故障转移(无需ODOWN)。
- SENTINEL sentinels {master}:查看 Sentinel 节点列表。
Redis集群
集群的架构与数据分片
-
哈希槽(Hash Slot)分配
-
分片规则:对键的
CRC16
值取模(CRC16(key) % 16384
)确定所属槽位。 -
哈希标签(Hash Tag):使用
{}
指定部分键名计算哈希值,强制相关键分配到同一槽。 -
槽分配管理:集群启动时,槽均匀分配到主节点,可通过
CLUSTER ADDSLOTS
手动分配或自动平衡。
-
-
节点角色
-
主节点(Master):负责处理槽的读写请求,参与故障选举。
-
从节点(Replica):复制主节点数据,主节点故障时接替其槽。
-
集群模式节点:所有节点默认开启集群模式(
cluster-enabled yes
)。
-
-
集群拓扑
-
最小部署:至少 3 个主节点(每个主节点至少 1 个从节点),共 6 个节点。
-
节点发现:节点通过 Gossip 协议交换状态信息(如
MEET
命令将节点加入集群)。
-
集群的工作机制
-
客户端请求路由
-
Smart Client:客户端缓存槽与节点的映射关系,直接向目标节点发送请求,若节点返回
MOVED
重定向错误,更新缓存并重试。 -
Dumb Client:依赖代理(如 Redis Proxy)转发请求,客户端无需感知集群拓扑。
-
-
数据读写流程
-
键存在目标槽:直接由负责该槽的节点处理。
-
键不在目标槽:返回
MOVED
错误,客户端重定向到正确节点。 -
槽迁移中:返回
ASK
错误,客户端临时重定向到迁移目标节点。
-
-
故障转移(Failover)
-
主观下线(PFAIL):节点 A 在
cluster-node-timeout
(默认 15 秒)内未收到节点 B 的响应,标记 B 为PFAIL
。 -
客观下线(FAIL):超过半数主节点确认节点 B 不可达,标记为
FAIL
,触发故障转移。 -
从节点选举:从节点发起选举,获得多数主节点投票后成为新主节点;接管原主节点的槽,并广播更新集群配置。
-
-
数据迁移与平衡
-
手动迁移:使用
CLUSTER SETSLOT <slot> IMPORTING/MIGRATING
命令迁移槽。 -
自动平衡:通过
redis-cli --cluster rebalance
自动调整槽分布,均衡负载。
-
集群的优缺点
-
优点
-
水平扩展:支持 TB 级数据和高并发访问。
-
高可用:自动故障转移,数据多副本存储。
-
去中心化:无单点故障,节点自治。
-
-
缺点
-
功能限制:不支持跨槽事务、部分命令受限(如
KEYS *
)。 -
运维复杂度:需管理分片、迁移、节点扩缩容。
-
客户端兼容性:需使用集群感知的客户端或代理。
-
生产环境建议
-
部署与配置
-
节点规划:主节点至少 3 个,跨物理机或可用区部署,从节点数 ≥ 主节点数。
-
网络优化:确保节点间低延迟通信,避免跨地域部署。
-
内存管理:监控节点内存使用,避免数据倾斜导致单个节点过载。
-
-
数据均衡
-
预分片:设计键时使用哈希标签,确保相关数据集中。
-
定期平衡:使用
redis-cli --cluster rebalance
调整槽分布。
-
-
监控与故障排查
-
关键指标:
CLUSTER INFO # 查看集群健康状态 CLUSTER NODES # 查看节点角色、槽分配、状态 INFO memory # 监控内存使用
-
日志分析:关注
CLUSTERDOWN
告警和节点超时事件。
-
常用集群命令
- CLUSTER NODES:查看集群节点信息。
- CLUSTER INFO:检查集群状态。
- CLUSTER FAILOVER:手动故障转移(从节点执行)。
Sentinel 与 Cluster 的对比
特性 | Sentinel | Cluster |
---|---|---|
数据分片 | 不支持,需客户端或代理分片。 | 内置分片(16384 槽)。 |
高可用 | 主从复制 + 故障转移。 | 每个分片主从复制,自动故障转移。 |
扩展性 | 垂直扩展(主节点性能瓶颈)。 | 水平扩展(支持大规模数据集和高吞吐)。 |
适用场景 | 中小规模,非分片架构。 | 大规模数据,高并发场景。 |
Redis复制
主从复制的建立流程
-
Redis 复制的建立分为 全量同步(Full Sync) 和 部分同步(Partial Sync) 两种模式,优先尝试部分同步以减少资源消耗。
-
从节点初始化连接
-
命令触发:从节点执行
SLAVEOF <master-ip> <master-port>
,开启复制流程。 -
连接主节点:从节点向主节点发起连接,发送
PING
确认网络可达性。
-
-
身份验证(可选):若主节点配置了
requirepass
,从节点需发送AUTH <password>
完成认证。 -
同步数据集
-
全量同步(SYNC):
主节点生成当前数据的 RDB 快照,通过子进程写入磁盘。
将 RDB 文件发送给从节点,同时缓存期间的写命令至 复制缓冲区(Replication Buffer)。
从节点接收 RDB 并加载到内存,再执行缓冲区中的写命令,追上主节点状态。
-
部分同步(PSYNC):
从节点发送
PSYNC <replid> <offset>
,携带自身记录的复制 ID 和偏移量。主节点检查复制 ID 和偏移量是否匹配历史记录:
匹配:发送
+CONTINUE
,传输从偏移量之后的写命令(利用 复制积压缓冲区)。不匹配:触发全量同步(
+FULLRESYNC
)。
-
-
命令传播(Command Propagation):同步完成后,主节点持续将写命令发送给从节点,保持数据一致。
复制的核心机制
-
复制ID与偏移量
-
复制ID(Replication ID):主节点的唯一标识,每次主节点重启或角色变更时生成新 ID。
-
偏移量(Offset):主从节点各自维护一个偏移量,记录已复制的数据量。
-
-
复制积压缓冲区(Replication Backlog)
-
作用:主节点维护一个固定大小的环形缓冲区(默认 1MB),缓存最近的写命令。
-
触发部分同步:若从节点的偏移量在缓冲区范围内,直接发送增量数据。
-
配置参数
repl-backlog-size 1mb # 缓冲区大小 repl-backlog-ttl 3600 # 主节点无连接时缓冲区保留时间(秒)
-
-
心跳检测与断线重连
-
心跳机制:主从节点定期确认存活状态和复制进度;主节点超时未收到心跳(默认 60 秒)则认为从节点下线。
-
断线处理:从节点重连后尝试部分同步,失败则触发全量同步。
复制拓扑与高级特性
-
级联复制(主-从-从)
-
场景:主节点连接过多从节点时,可通过级联复制分摊压力。
-
配置:将从节点(Slave A)作为另一从节点(Slave B)的主节点。
-
-
延迟副本(Lagging Replica)
-
作用:人为设置从节点延迟同步,用于误操作恢复(需第三方工具支持)。
-
实现:通过
slave-repl-delay
配置延迟时间(Redis 自身不原生支持,需外部控制)。
-
复制的问题与优化
-
全量同步的资源消耗
-
问题:大数据集时生成和传输 RDB 文件会阻塞主节点并占用带宽。
-
优化:增大
repl-backlog-size
减少全量同步概率;使用无盘同步(repl-diskless-sync yes
),但需主节点内存充足。
-
-
复制延迟
-
原因:网络延迟、从节点负载过高或主节点写入压力大。
-
监控:通过
INFO replication
的slave_repl_offset
与master_repl_offset
差值判断延迟。 -
优化:提升网络带宽,减少主从节点跨地域部署;限制主节点写入速率(如使用管道批量写入)。
-
-
数据不一致
-
原因:主从网络中断导致部分数据未同步。
-
检测:使用
redis-cli --slave
模拟从节点检查数据差异。 -
修复:手动触发全量同步(
SLAVEOF NO ONE
+ 重新配置复制)。
-