高 困难
Redis集群方案#
一句话答案#
三种高可用方案:主从复制(基础)、Sentinel(自动故障转移)、Cluster(分片+高可用,16384 槽)。
核心要点
三种高可用方案对比:
| 特性 | 主从复制 | Sentinel 哨兵 | Redis Cluster |
|---|---|---|---|
| 数据分片 | ❌ | ❌ | ✅ 16384 slot |
| 自动故障转移 | ❌ 需手动 | ✅ | ✅ |
| 写扩展 | ❌ 单主 | ❌ 单主 | ✅ 多主 |
| 适用场景 | 读写分离 | 读多写少、单机内存够 | 大数据量、高写入 |
选型决策:
数据量能装进单机内存?
├─ 能 → 用 Sentinel(简单可靠,自动故障转移)
└─ 不能 → 用 Cluster(分片 + 高可用)plaintextCluster 故障检测过程:
1. PFAIL(Probable Fail,疑似下线):
节点 A 向节点 B 发送 PING,超过 cluster-node-timeout 未收到 PONG
→ A 将 B 标记为 PFAIL(仅本地判断)
2. FAIL(确认下线):
A 通过 Gossip 告诉其他节点"B 可能下线了"
当集群中超过半数的主节点都将 B 标记为 PFAIL
→ B 被标记为 FAIL(广播给所有节点)
→ 触发故障转移
注意:只有主节点参与投票,从节点不参与
类似 Sentinel 的 SDOWN → ODOWN 过程plaintext从节点选举和故障转移:
当某主节点被标记为 FAIL 后:
1. 该主节点的从节点发起选举:
① 从节点增加自己的 currentEpoch(逻辑时钟)
② 向所有主节点广播 FAILOVER_AUTH_REQUEST(请求投票)
2. 主节点投票:
每个主节点在一个 epoch 中只投一票(先到先得)
投给复制偏移量最大的从节点(数据最完整)
3. 从节点获得超过半数主节点的投票 → 当选新主节点
4. 新主节点执行:
① 执行 SLAVEOF NO ONE(取消复制,成为主节点)
② 接管已故障主节点的所有 slot
③ 广播 PONG 消息,告知集群拓扑变更
④ 其他从节点(如果有多个)指向新主节点plaintextGossip 协议——节点间如何同步状态(深挖)。
Cluster 是去中心化的,没有配置中心,所有节点的集群视图(谁在线、谁负责哪些 slot)靠 Gossip(流言/流行病协议)互相传播,最终一致。
工作方式(每个节点每秒做一次心跳):
1. 随机选几个节点发 PING(不是全广播)
2. 收到 PING 的节点回 PONG
3. PING/PONG 包里都"捎带"携带一部分其他节点的状态
(随机带约 1/10 节点的 gossip 信息 + slot 位图 2KB)
4. 这样状态像流言一样一传十、十传百扩散开
→ 不需要任何节点掌握全局,几轮传播后全网达成最终一致plaintext为什么这样设计: 节点选择随机、信息片段化捎带,避免了”每个节点都向所有节点广播”的 O(N²) 瞬时风暴;故障信息(PFAIL/FAIL)、新节点加入、slot 变更都靠它扩散。
节点数受限的根因(心跳带宽是 O(N²)):
N 个节点,每个节点每秒都在和若干节点交换包,
每个包还携带 O(N) 的节点状态 + 2KB slot 位图,
总通信量随 N² 增长 → N 太大时心跳流量本身吃满带宽
这就是 Redis 官方建议 Cluster 节点数 ≤ 1000 的根本原因
注:节点长时间没被随机 PING 到时,会被强制选中补发 PING,保证覆盖plaintext整个集群不可用的条件:
任意主节点下线且没有可用的从节点 → 该节点负责的 slot 无法服务
默认:cluster-require-full-coverage = yes → 有 slot 不可用则整个集群拒绝写入
设为 no → 仅该部分 slot 不可用,其他 slot 正常服务plaintext面试回答(2分钟版)
Redis 高可用有三种主流方案,是逐步演进的关系。最基础的是主从复制,从库通过 PSYNC 命令做全量同步(RDB 快照)和增量同步(repl_backlog 环形缓冲区),但主库故障需要手动切换。第二层是 Sentinel 哨兵,在主从基础上加入自动故障检测和转移,通过主观下线到客观下线的投票机制确认主库故障,然后选举 Leader Sentinel 执行切换,但写能力仍受限于单主节点。第三层是 Redis Cluster,把数据分成 16384 个槽分布在多个主节点上,既做了分片又内置了高可用,每个分片内部仍然是主从复制。选型上我的判断标准是:数据量能装进单机内存就用哨兵方案,装不下就上 Cluster。Cluster 需要注意的是不支持跨槽事务,Gossip 协议的通信开销限制了节点数量一般不超过千个。
追问与易错
追问方向:
- “三种方案怎么选?”→ 数据量能装进单机内存且写压力不大用 Sentinel 哨兵(简单可靠);数据量超出单机内存或需要水平扩展写能力用 Cluster;纯读写分离用主从复制即可
- “Cluster 支持事务吗?”→ 仅支持同一 slot 内的事务(MULTI/EXEC)和 Lua 脚本;跨 slot 操作不支持事务,需要用 Hash Tag(大括号)将相关 key 路由到同一 slot
- “从主从升级 Cluster 注意什么?”→ 需要评估跨 slot 操作(MGET/Pipeline/事务/Lua)是否兼容、客户端 SDK 是否支持 Cluster 模式、数据迁移方案(redis-shake 等工具)、Hash Tag 改造以及业务灰度验证
易错点:
- ❌ Sentinel 和 Cluster 一样——前者不分片
- ❌ Cluster 节点越多越好——Gossip 开销增加