Redis 哨兵与集群
1. 三种部署模式对比
Section titled “1. 三种部署模式对比”单节点 ──▶ 主从复制 ──▶ 哨兵模式 ──▶ 集群模式 简单 读写分离 自动故障转移 水平扩展 无HA 无自动HA 单Master HA 多Master HA| 模式 | 高可用 | 水平扩展 | 复杂度 | 适用场景 |
|---|---|---|---|---|
| 单节点 | ❌ | ❌ | 低 | 开发/测试 |
| 主从复制 | ❌(需人工切换) | 读扩展 ✅ | 低 | 读多写少,可接受人工运维 |
| 哨兵模式 | ✅ 自动故障转移 | 读扩展 ✅ | 中 | 写少、单 Master 能承载 |
| 集群模式 | ✅ 自动故障转移 | 读写均可扩展 ✅ | 高 | 大数据量、高并发写 |
2. 哨兵模式(Sentinel)
Section titled “2. 哨兵模式(Sentinel)”2.1. 架构与作用
Section titled “2.1. 架构与作用”哨兵模式在主从复制基础上,增加若干 Sentinel(哨兵)节点监控集群健康状态,Master 宕机时自动选举新 Master:
Client │ ▼ Sentinel 集群(奇数个,通常 3 个) ┌───────────┬───────────┬───────────┐ │Sentinel 1 │Sentinel 2 │Sentinel 3 │ └─────┬─────┴─────┬─────┴─────┬─────┘ │监控 │ │ ┌─────▼─────┐ ┌──▼──────┐ ┌──▼──────┐ │ Master │─▶│ Slave 1 │ │ Slave 2 │ └───────────┘ └─────────┘ └─────────┘哨兵的三大职责:
| 职责 | 说明 |
|---|---|
| 监控(Monitoring) | 每秒向 Master/Slave/其他 Sentinel 发送 PING,检测节点存活 |
| 通知(Notification) | 节点异常时通过 API 通知运维人员或其他系统 |
| 自动故障转移(Failover) | Master 宕机后,自动选举新 Master,更新从节点配置 |
2.2. 故障判定流程
Section titled “2.2. 故障判定流程”主观下线(SDOWN):单个 Sentinel 在 down-after-milliseconds 内未收到 Master 响应──▶ 标记为"主观下线"(可能是网络抖动,单票不算数)
客观下线(ODOWN):超过 quorum 个 Sentinel 都认为 Master 主观下线──▶ 标记为"客观下线"(确认宕机,触发故障转移)
Sentinel Leader 选举:Sentinel 间投票选出 Leader──▶ Leader 负责执行故障转移
故障转移:1. 从 Slave 中选出新 Master(按优先级、复制偏移量等)2. 将其他 Slave 指向新 Master3. 将客户端连接切换到新 Master4. 原 Master 恢复后作为新的 Slave 加入2.3. Docker Compose 搭建
Section titled “2.3. Docker Compose 搭建”version: '3'services: redis-master: image: redis:7.0 container_name: redis-master ports: - "6379:6379" command: redis-server --requirepass 123456
redis-slave1: image: redis:7.0 container_name: redis-slave1 ports: - "6380:6379" command: redis-server --requirepass 123456 --masterauth 123456 --replicaof redis-master 6379
redis-slave2: image: redis:7.0 container_name: redis-slave2 ports: - "6381:6379" command: redis-server --requirepass 123456 --masterauth 123456 --replicaof redis-master 6379
sentinel1: image: redis:7.0 container_name: sentinel1 ports: - "26379:26379" command: > redis-sentinel /etc/redis/sentinel.conf volumes: - ./sentinel.conf:/etc/redis/sentinel.confport 26379sentinel monitor mymaster redis-master 6379 2 # quorum = 2sentinel auth-pass mymaster 123456sentinel down-after-milliseconds mymaster 5000 # 5 秒无响应判主观下线sentinel failover-timeout mymaster 10000 # 故障转移超时sentinel parallel-syncs mymaster 1 # 同时重新配置的 Slave 数量2.4. SpringBoot 连接哨兵
Section titled “2.4. SpringBoot 连接哨兵”spring: data: redis: sentinel: master: mymaster # sentinel.conf 中配置的 master 名称 nodes: - 192.168.1.10:26379 - 192.168.1.11:26379 - 192.168.1.12:26379 password: 123456 lettuce: pool: max-active: 8客户端连接哨兵后,会自动感知 Master 切换,无需手动更改连接地址。
3. 集群模式(Cluster)
Section titled “3. 集群模式(Cluster)”3.1. 架构与数据分片
Section titled “3.1. 架构与数据分片”Redis Cluster 将数据分散到多个 Master 节点,每个 Master 负责一部分数据,所有节点共同对外提供服务:
Redis Cluster(3 Master + 3 Slave):
Master1 ──▶ Slave1 Master2 ──▶ Slave2 Master3 ──▶ Slave3槽 0~5460 槽 5461~10922 槽 10923~16383哈希槽(Hash Slot): Redis Cluster 将数据空间划分为 16384 个槽,每个 key 通过 CRC16(key) % 16384 计算所属槽,再路由到对应 Master:
SET user:1001 "Alice" │ ▼CRC16("user:1001") % 16384 = 7638 │ ▼槽 7638 属于 Master2 │ ▼数据写入 Master23.2. 请求重定向(MOVED / ASK)
Section titled “3.2. 请求重定向(MOVED / ASK)”客户端请求到错误节点时,节点返回重定向指令:
客户端 ──▶ Master1(发送 SET user:1001) │ └── 该 key 属于槽 7638,在 Master2 ──▶ 返回 MOVED 7638 Master2:6379 │客户端 ──▶ Master2(重新发送 SET user:1001)✅3.3. 集群搭建(Docker Compose)
Section titled “3.3. 集群搭建(Docker Compose)”version: '3'services: redis-node1: image: redis:7.0 container_name: redis-node1 ports: - "7001:7001" - "17001:17001" # 集群总线端口(= 数据端口 + 10000) command: > redis-server --port 7001 --cluster-enabled yes --cluster-config-file nodes-7001.conf --cluster-node-timeout 5000 --requirepass 123456 --masterauth 123456
redis-node2: image: redis:7.0 container_name: redis-node2 ports: - "7002:7002" - "17002:17002" command: > redis-server --port 7002 --cluster-enabled yes --cluster-config-file nodes-7002.conf --cluster-node-timeout 5000 --requirepass 123456 --masterauth 123456
# ... node3~node6 类似配置初始化集群(6 节点:3 主 3 从):
redis-cli -a 123456 --cluster create \ 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 \ 127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006 \ --cluster-replicas 1 # 每个 Master 配 1 个 Slave3.4. SpringBoot 连接集群
Section titled “3.4. SpringBoot 连接集群”spring: data: redis: cluster: nodes: - 192.168.1.10:7001 - 192.168.1.10:7002 - 192.168.1.10:7003 - 192.168.1.11:7001 - 192.168.1.11:7002 - 192.168.1.11:7003 max-redirects: 3 # 最大重定向次数 password: 123456 lettuce: cluster: refresh: adaptive: true # 自适应刷新集群拓扑(节点变化时自动更新) period: 2000ms # 定期刷新间隔4. 集群模式的注意事项
Section titled “4. 集群模式的注意事项”4.1. 多 key 操作限制
Section titled “4.1. 多 key 操作限制”// ❌ 跨槽的 MGET 会报错(key 不在同一槽)redisTemplate.opsForValue().multiGet(List.of("user:1", "order:1"));
// ✅ 使用 Hash Tag 强制同槽({} 内的内容决定槽位)// "user:{1001}:info" 和 "order:{1001}:latest" 都路由到槽 {1001} 所在的节点redisTemplate.opsForValue().multiGet(List.of("user:{1001}:info", "order:{1001}:latest"));4.2. 事务和 Lua 脚本
Section titled “4.2. 事务和 Lua 脚本”事务(MULTI/EXEC)和 Lua 脚本只能操作同一节点上的 key,使用 Hash Tag 保证相关 key 在同一节点。
4.3. 集群 vs 哨兵选型
Section titled “4.3. 集群 vs 哨兵选型”数据量 < 20GB 且单 Master 写入能够承载 └──▶ 哨兵模式(运维简单)
数据量大 或 写入 QPS 超过单节点上限(约 8~10 万) └──▶ 集群模式(水平扩展)5. 故障转移对比
Section titled “5. 故障转移对比”| 对比项 | 哨兵模式 | 集群模式 |
|---|---|---|
| Master 宕机恢复时间 | 秒级(约 10~30 秒) | 秒级 |
| 数据分片 | ❌ 单 Master 存全量数据 | ✅ 数据分散到多 Master |
| 最大存储容量 | 单机内存上限 | 理论无上限(加节点扩展) |
| 跨节点操作 | 无限制 | 受哈希槽限制 |
| 运维复杂度 | 中等 | 较高 |
| 最少节点数 | 1 Master + 1 Slave + 3 Sentinel | 6 个(3 主 3 从) |