Redis 高可用:从主从复制到集群架构的演进之路
Redis 高可用从主从复制到集群架构的演进之路本文将从零开始带你全面理解 Redis 高可用架构的演进历程包括主从复制、哨兵模式、集群架构以及生产环境中的最佳实践。一、为什么需要高可用1.1 单机 Redis 的问题Redis 作为高性能的键值存储系统在单机模式下存在明显的瓶颈问题描述影响单点故障节点宕机后服务完全不可用业务中断用户体验受损容量限制受限于单机内存通常 ≤ 64GB无法存储海量数据性能瓶颈读写能力受限于单核 CPU无法应对高并发场景维护困难停机维护期间服务不可用无法做到无感知升级1.2 高可用演进路线单机 → 主从复制 → 哨兵模式 → 集群架构 │ │ │ │ ▼ ▼ ▼ ▼ 备份 读写分离 自动故障转移 水平扩展二、主从复制数据冗余的起点2.1 什么是主从复制主从复制是指将主节点的数据同步到从节点实现数据的冗余备份。┌─────────────────────────────────────────────────────────────────────┐ │ 主从复制架构 │ ├─────────────────────────────────────────────────────────────────────┤ │ │ │ 写请求 ──▶ 主节点 ──▶ 从节点1只读 │ │ │ │ │ └──────▶ 从节点2只读 │ │ │ │ 特点 │ │ • 主节点可读写从节点只读 │ │ • 数据自动从主同步到从 │ │ • 支持一主多从从节点可以再有从节点 │ │ │ └─────────────────────────────────────────────────────────────────────┘2.2 核心原理主从复制分为两个阶段全量同步首次连接从节点发送 PSYNC 命令请求同步主节点 fork 子进程生成 RDB 快照主节点将 RDB 文件发送给从节点从节点清空旧数据加载 RDB主节点将期间的写命令发送给从节点增量同步正常运行主节点每执行一条写命令就发送给从节点从节点执行相同的命令保持数据一致关键概念复制偏移量标记已同步的数据位置复制积压缓冲区存储最近的写命令用于断线重连后的增量同步2.3 优缺点分析优点缺点✅ 数据冗余备份❌ 主节点宕机需人工介入✅ 读写分离分担读压力❌ 写操作仍在单节点✅ 实现简单❌ 无法自动故障转移✅ 从节点可做离线分析❌ 数据容量受限于主节点内存2.4 快速搭建# 启动主节点redis-server--port6379# 启动从节点redis-server--port6380--slaveof127.0.0.16379redis-server--port6381--slaveof127.0.0.16379# 查看复制状态redis-cli INFO replication三、哨兵模式自动故障转移3.1 什么是哨兵哨兵Sentinel是 Redis 官方提供的高可用解决方案它可以监控主从节点并在主节点故障时自动完成故障转移。┌─────────────────────────────────────────────────────────────────────┐ │ 哨兵模式架构 │ ├─────────────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ │ 哨兵1 │ │ 哨兵2 │ │ 哨兵3 │ ← 监控集群 │ │ └────┬────┘ └────┬────┘ └────┬────┘ │ │ │ │ │ │ │ └────────────┼────────────┘ │ │ ▼ │ │ ┌──────────┐ │ │ │ 主节点 │ │ │ └────┬─────┘ │ │ │ │ │ ┌──────┴──────┐ │ │ ▼ ▼ │ │ ┌──────┐ ┌──────┐ │ │ │从节点│ │从节点│ │ │ └──────┘ └──────┘ │ │ │ └─────────────────────────────────────────────────────────────────────┘3.2 三大职责职责说明监控定时检查主从节点是否存活选主主节点下线后选举新主节点通知通知客户端新主节点地址3.3 下线判断机制主观下线单个哨兵认为主节点下线SDOWN客观下线超过法定人数quorum的哨兵都认为主节点下线ODOWN3.4 选主算法哨兵选择新主节点的优先级排除下线和断连过久的从节点按slave-priority配置排序数字越小越优先优先级相同比较复制偏移量数据越新越优先偏移量相同比较 runid字典序越小越优先3.5 配置文件示例# sentinel.conf port 26379 sentinel monitor mymaster 127.0.0.1 6379 2 sentinel down-after-milliseconds mymaster 30000 sentinel failover-timeout mymaster 180000 sentinel parallel-syncs mymaster 13.6 优缺点分析优点缺点✅ 自动故障转移❌ 故障转移期间写操作不可用✅ 无需人工介入❌ 配置相对复杂✅ 支持多哨兵防止误判❌ 数据容量仍受单机限制四、集群架构水平扩展的终极方案4.1 什么是 Redis ClusterRedis Cluster 是 Redis 的分布式解决方案通过分片Sharding将数据分散到多个节点实现水平扩展。4.2 核心概念哈希槽Redis Cluster 将整个数据空间划分为16384 个哈希槽slot CRC16(key) % 16384┌─────────────────────────────────────────────────────────────────────┐ │ 哈希槽分布 │ ├─────────────────────────────────────────────────────────────────────┤ │ │ │ 节点1 节点2 节点3 │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ │ 0~5460 │ │5461~10922│ │10923~16383│ │ │ │ 5461个槽 │ │ 5462个槽 │ │ 5461个槽 │ │ │ └─────────┘ └─────────┘ └─────────┘ │ │ │ │ 每个节点知道自己负责哪些槽也知道其他节点负责哪些槽 │ │ │ └─────────────────────────────────────────────────────────────────────┘4.3 客户端定位数据流程客户端请求 user:1001 │ ▼ 计算 slot CRC16(user:1001) % 16384 5230 │ ▼ 查槽表slot 5230 → 节点1 │ ▼ 发送请求到节点1 │ ▼ 节点1 检查自己是否负责该槽 ├── 是 → 直接返回数据 └── 否 → 返回 MOVED 重定向4.4 节点通信Gossip 协议集群节点之间通过 Gossip 协议通信每个节点定期随机与其他节点交换信息消息类型作用PING检测节点是否存活PONG响应 PING或主动广播状态MEET新节点加入集群FAIL广播节点下线4.5 集群搭建Docker Compose# docker-compose.ymlversion:3.8services:redis-node-1:image:redis:7command:redis-server--port 6379--cluster-enabled yesports:-7001:6379redis-node-2:image:redis:7command:redis-server--port 6379--cluster-enabled yesports:-7002:6379redis-node-3:image:redis:7command:redis-server--port 6379--cluster-enabled yesports:-7003:6379# 初始化集群cluster-init:image:redis:7depends_on:-redis-node-1-redis-node-2-redis-node-3command:sh -c echo yes | redis-cli --cluster create redis-node-1:6379 redis-node-2:6379 redis-node-3:6379 --cluster-replicas 04.6 集群操作命令# 创建集群redis-cli--clustercreate192.168.1.1:6379192.168.1.2:6379192.168.1.3:6379# 查看集群节点redis-cli CLUSTER NODES# 查看集群信息redis-cli CLUSTER INFO# 查看槽分配redis-cli CLUSTER SLOTS# 添加节点redis-cli--clusteradd-node new_host:new_port existing_host:existing_port# 重新分配槽redis-cli--clusterreshard host:port4.7 优缺点分析优点缺点✅ 水平扩展容量无限❌ 实现复杂运维成本高✅ 高吞吐写性能随节点线性提升❌ 客户端需支持集群协议✅ 自动故障转移❌ 多 key 操作受限✅ 无中心化架构❌ 批量操作需要同一槽五、三种架构对比对比维度主从复制哨兵模式集群架构数据容量受限于单机受限于单机可水平扩展写性能受限于单机受限于单机随节点线性增长读性能可增加从节点可增加从节点随节点线性增长故障转移手动自动自动客户端复杂度低中高运维复杂度低中高适用场景数据量 50GB数据量 50GB大数据量、高吞吐六、生产环境最佳实践6.1 架构选型建议场景推荐架构理由数据量 50GB可接受短暂停机主从复制简单够用数据量 50GB需要高可用哨兵模式1主2从3哨兵自动故障转移数据量 50GB或高吞吐要求集群架构3主3从起水平扩展云原生环境集群架构弹性伸缩6.2 配置推荐# 通用配置 maxmemory 16gb maxmemory-policy allkeys-lru # 主从配置从节点 replica-read-only yes replica-serve-stale-data yes # 哨兵配置 sentinel monitor mymaster redis-master 6379 2 sentinel down-after-milliseconds mymaster 30000 sentinel failover-timeout mymaster 180000 # 集群配置 cluster-enabled yes cluster-node-timeout 15000 cluster-migration-barrier 16.3 监控指标指标说明告警阈值connected_slaves连接的从节点数 配置值master_repl_offset主节点复制偏移量关注变化cluster_state集群状态不为 okcluster_slots_assigned已分配槽数 16384七、常见面试题Q1: 主从复制的全量同步和增量同步分别在什么情况下触发全量同步从节点第一次连接主节点从节点断线重连但 offset 不在 backlog 范围内主节点 runid 不匹配增量同步从节点断线重连offset 仍在 backlog 范围内正常运行期间持续进行Q2: 哨兵模式下为什么需要奇数个哨兵为了投票。3 个哨兵最多投 2 票4 个哨兵也可能只投 2 票。奇数个哨兵更容易达成共识避免脑裂问题。Q3: 为什么 Redis Cluster 是 16384 个槽心跳包中需要携带槽信息16384 个槽的位图只有 2KB集群规模建议不超过 1000 个节点16384 足够分配在空间和灵活性之间取得平衡Q4: 集群模式下如何支持多 key 操作使用 hash tag{user:1001}:name和{user:1001}:age会被分配到同一个槽。只有同一槽内的多个 key 才能进行批量操作。八、总结从单机到主从、从主从到哨兵、从哨兵到集群Redis 的高可用架构经历了三个重要阶段主从复制解决了数据备份和读写分离的问题但无法自动故障转移哨兵模式在主从复制的基础上实现了自动故障转移但数据容量仍受单机限制集群架构通过分片实现了水平扩展支持海量数据和高吞吐场景在实际生产中应根据业务需求选择合适的架构小规模应用 50GB哨兵模式足够大规模应用 50GB必须使用集群架构追求极致性能可考虑读写分离 本地缓存组合参考资料Redis 官方文档Redis 主从复制Redis 哨兵Redis 集群本文是 Redis 学习系列的一部分后续会继续分享缓存三大问题、大 Key 排查治理等实战内容欢迎关注交流。