Redis篇(七):集群模式、主从同步与哨兵机制
一、Redis 集群模式演进主从 → 哨兵 → 切片集群Redis 提供了三种集群模式分别解决不同层面的问题数据备份、高可用、横向扩展。1.1 主从模式Replication核心设计一主多从读写分离。主节点可读可写从节点只读主节点的写操作异步同步给从节点。# 从节点配置replicaof192.168.1.1006379特点实现简单配置方便支持读写分离提升读性能主从复制是异步的无法保证强一致性主节点故障需手动切换适用场景数据备份、读写分离、开发测试环境。1.2 哨兵模式Sentinel核心设计在主从模式基础上增加哨兵节点自动监控主从状态实现故障自动转移。# sentinel.confsentinel monitor mymaster192.168.1.10063792sentinel down-after-milliseconds mymaster5000sentinel failover-timeout mymaster60000特点自动监控主从节点健康状态主节点故障时自动选举新主客户端自动切换通过订阅 switch-master 频道但单节点容量瓶颈仍未解决适用场景生产环境高可用、自动容灾。1.3 切片集群Redis Cluster核心设计将数据分布在多个节点上通过 16384 个哈希槽实现数据分片支持多主多从和横向扩展。# 创建集群redis-cli--clustercreate192.168.1.101:6379192.168.1.102:6379192.168.1.103:6379192.168.1.104:6379192.168.1.105:6379192.168.1.106:6379 --cluster-replicas1特点数据分布式存储支持横向扩展无中心架构每个节点保存完整槽位映射支持在线扩容/缩容槽迁移自动故障转移类似哨兵适用场景海量数据、高并发、需要横向扩展的生产环境。1.4 三种模式核心能力对比能力主从哨兵切片集群高可用✗✓✓自动故障转移✗✓✓横向扩展✗✗✓数据分片✗✗✓读写分离✓✓✓二、Redis 切片集群工作原理2.1 哈希槽分片机制Redis Cluster 采用**哈希槽Hash Slot**进行数据分片共 16384 个槽位0 ~ 16383。槽位计算slot CRC16(key) % 16384CRC16 算法计算 key 的 16bit 哈希值取模运算对 16384 取模得到槽位号为什么是 163842^14 16384用 14bit 即可表示节省心跳包中的槽位图空间节点数通常在 1000 以内16384 个槽位足够均匀分配槽迁移时粒度适中不会过大或过小2.2 哈希槽与节点的对应关系平均分配集群创建时自动分配# 3 主 3 从自动平均分配Master-A:0~5460Master-B:5461~10922Master-C:10923~16383手动分配通过命令调整# 将槽 0~1000 分配给节点 Aredis-cli--clusterreshard192.168.1.101:6379 --cluster-from all --cluster-to nodeA_id --cluster-slots1001注意必须将 16384 个槽位全部分配完集群才能正常工作。2.3 Cluster 核心特性特性说明无中心架构每个节点保存完整的槽位映射表无单点瓶颈客户端直连MOVED 重定向槽已迁移/ ASK 重定向槽正在迁移槽迁移在线扩容/缩容不影响服务Gossip 协议节点间通过 PING/PONG 交换状态信息三、主从同步全量同步 vs 增量同步Redis 主从复制分为全量同步和增量同步两种机制根据场景自动选择。3.1 全量同步Full Resynchronization触发条件从节点首次连接主节点主从 replid 不匹配主节点重启或数据重置从节点 offset 超出主节点 repl_backlog 范围执行流程① 从节点发送 PSYNC ? -1首次连接 ↓ ② 主节点返回 FULLRESYNC replid offset ↓ ③ 主节点执行 BGSAVE 生成 RDB 快照 ↓ ④ 主节点将 RDB 文件传输给从节点 ↓ ⑤ 从节点清空旧数据加载 RDB ↓ ⑥ 主节点将复制缓冲区的写命令发送给从节点 ↓ ⑦ 从节点执行增量命令完成同步关键概念概念说明replid复制 ID主节点的唯一标识40 位随机字符串offset复制偏移量标记同步进度复制缓冲区全量同步期间缓存的新写命令repl_backlog环形复制积压缓冲区默认 1MB3.2 增量同步Partial Resynchronization触发条件主从短暂断开后重连从节点的 offset 仍在主节点 repl_backlog 范围内执行流程① 从节点发送 PSYNC replid offset断线重连 ↓ ② 主节点校验 offset 是否在 repl_backlog 中 ↓ ③ 主节点返回 CONTINUE ↓ ④ 主节点推送缺失的写命令 ↓ ⑤ 从节点执行增量命令 ↓ ⑥ 同步完成主服务器如何知道发送哪些增量数据主节点维护一个环形复制积压缓冲区repl_backlog_buffer记录最近的写命令。当从节点重连时主节点根据从节点提供的 offset从 backlog 中找到差异数据如果 offset 在 backlog 范围内 →增量复制如果 offset 超出 backlog 范围 →全量复制3.3 生产配置建议# redis.conf# repl-backlog-size 建议设置为写入量的 1~2 小时repl-backlog-size 128mb# 从节点数量较多时减少网络包数量repl-disable-tcp-nodelayyes# 主从节点部署在同一机房降低网络延迟四、哨兵机制故障发现、选举与自动切换哨兵Sentinel是 Redis 的高可用解决方案负责监控主从节点、自动故障转移、通知客户端。4.1 哨兵监控流程1. 主观下线SDOWN哨兵周期性向主从节点发送 PING 命令 ↓ 节点超时未响应默认 30s ↓ 标记为「主观下线」单个哨兵的判断2. 客观下线ODOWN哨兵向其他哨兵询问该节点状态 ↓ 多数哨兵同意该节点已下线 ↓ 标记为「客观下线」触发故障转移4.2 Leader 选举哨兵集群中需要选举一个 Leader 来执行故障转移发现客观下线的哨兵成为候选者 ↓ 候选者向其他哨兵发送拉票请求 ↓ 每个哨兵只有一票可投给自己或他人只有候选者可投给自己 ↓ 获得半数以上票数 → 成为 Leader4.3 新主节点选择规则Leader 从从节点中选择新主进行三轮考察轮次考察维度规则第一轮优先级slave-priority优先级越小越靠前0 表示不参与选举第二轮复制进度replication offset接收数据越多越靠前数据越新第三轮Run IDID 越小越靠前打破平局4.4 故障转移完成后的操作① 让已下线主节点属下的所有从节点指向新主节点 ② 向 switch-master 频道发布新主节点信息 ③ 客户端订阅该频道自动切换到新主 ④ 旧主节点重新上线后哨兵发送 SLAVEOF 命令降级为从节点4.5 典型架构3 个 Sentinel 节点 1 主 2 从最小高可用配置 Sentinel 节点数应为奇数至少 3 个避免脑裂五、主从数据不一致与过期 key 处理5.1 如何避免主从数据不一致方案一降低网络延迟主从节点部署在同一机房使用专线或内网通信方案二复制进度监控// 监控主从复制偏移量差longmasterOffsetgetMasterReplOffset();longslaveOffsetgetSlaveReplOffset();if(masterOffset-slaveOffsetTHRESHOLD){// 复制延迟过大禁止在该从节点读取routeToOtherSlave();}方案三强制读主对于强一致性要求的场景直接读取主节点牺牲部分读性能。5.2 主从架构中过期 key 如何处理主节点执行过期删除后发送 DEL 命令给从节点从节点不主动删除过期 key收到主节点的 DEL 命令后才删除读取时从节点可能返回逻辑上已过期但实际仍存在的数据直到收到 DEL详细机制可参考本专栏第四篇《过期键删除策略、内存淘汰与持久化的协同机制》。5.3 主从复制是同步还是异步异步复制。主节点收到写命令后先写入内部缓冲区然后异步发送给从节点。具体流程客户端发送写命令 ↓ 主节点执行命令 ↓ 写入复制缓冲区 ↓ 异步发送给从节点 ↓ 从节点接收并执行全量同步期间主节点生成 RDB、传输 RDB、从节点加载 RDB 都需要时间这段时间内的新写命令会被缓存到复制缓冲区待 RDB 加载完成后发送给从节点。六、脑裂问题成因与解决方案6.1 什么是脑裂脑裂场景主节点与所有从节点网络断开 ↓ 但主节点与客户端网络正常 ↓ 客户端继续向旧主写入数据 ↓ 哨兵发现主节点失联选举新主 ↓ 集群出现两个主节点旧主 新主 ↓ 网络恢复后旧主被降级为从数据清空 ↓ 脑裂期间写入的数据全部丢失6.2 如何减少主从切换带来的数据丢失方案一配置 min-slaves 限制# redis.conf# 当从节点数量少于 2 个或复制延迟超过 10 秒时主节点拒绝写请求min-slaves-to-write2min-slaves-max-lag10原理脑裂发生时旧主与从节点失联从节点数量变为 0触发 min-slaves-to-write 限制旧主拒绝写请求客户端收到错误可将数据写入本地缓存或消息队列新主上线后数据写入新主避免丢失方案二客户端降级处理// 主节点不可写时降级到本地缓存publicvoidwriteData(Stringkey,Stringvalue){try{redisTemplate.opsForValue().set(key,value);}catch(RedisCommandExecutionExceptione){// 主节点拒绝写入降级到本地缓存localCache.put(key,value);// 异步同步到消息队列mqProducer.send(newCacheSyncMessage(key,value));}}方案三异步复制同步丢失的阈值控制# 配置复制延迟阈值# 当所有从节点的复制延迟都超过阈值时主节点拒绝写请求# 客户端发现后采取降级措施6.3 脑裂 vs 数据丢失对比场景数据丢失原因解决方案异步复制延迟主节点已写入从节点未同步主节点宕机min-slaves 限制 监控脑裂旧主被降级数据清空min-slaves 客户端降级全量同步期间从节点加载 RDB 时主节点新数据未同步复制缓冲区 增量同步七、综合对比表机制核心作用使用场景关键配置主从复制数据备份、读写分离数据冗余、读多写少replicaof全量同步首次同步或数据差异大新从节点加入repl-backlog-size增量同步断线重连快速恢复网络闪断repl-backlog-size哨兵自动故障转移生产高可用sentinel monitor切片集群数据分片、横向扩展海量数据cluster-enabledmin-slaves防止脑裂数据丢失强一致性要求min-slaves-to-write如果本文对你有帮助欢迎点赞 收藏 ⭐ 关注 你的支持是我持续创作的动力