5. 高可用:主从 / Sentinel / Cluster
❓ 面试官:Redis 怎么保证高可用?如果单节点挂了怎么办?
频率:🔥🔥🔥🔥🔥
💡 一句话总结(先抛结论): Redis 保证高可用的演进路线是:主从复制(解决单点故障,实现读写分离) $\rightarrow$ 哨兵模式(解决主从无法自动故障转移的问题) $\rightarrow$ Cluster 集群(解决单节点内存容量和写并发瓶颈)。
📝 详细原理解析:
主从复制(Master-Slave):
- 架构:一主多从。主节点负责写操作,从节点负责读操作。
- 痛点:如果主节点宕机,需要人工登录服务器,手动把某个从节点提升为主节点(执行
replicaof no one),然后再把其他从节点指向新主节点。在此期间,整个系统处于不可写状态。
哨兵模式(Sentinel):
- 架构:在主从架构的基础上,引入了一组“哨兵”节点(通常是 3 个,奇数个防止脑裂)。
- 作用:监控、自动故障转移、通知客户端。
- 原理:哨兵们会不断地向主从节点发送
PING命令。如果发现主节点没响应(主观下线),哨兵们会互相协商,当大多数哨兵都认为主节点挂了(客观下线),就会自动选举出一个新的主节点,并将这个变化通知给应用程序(如 Redisson 客户端)。
❓ 面试官:那既然有了哨兵模式实现高可用,为什么还要出 Redis Cluster 集群呢?【中级】
频率:🔥🔥🔥🔥
💡 一句话总结(先抛结论): 因为主从+哨兵模式无法解决海量数据存储和超高并发写的问题。不管你加多少个从节点,真正能执行写操作的始终只有那一个主节点。如果你的缓存数据有 100GB,单台机器的内存根本放不下。
📝 详细原理解析:
- Cluster 集群解决的痛点:它是一种真正的分布式分片(Sharding)架构。它将数据分散存储在多个主节点上。
- 哈希槽(Hash Slot)机制:
- Cluster 集群没有使用一致性哈希,而是引入了 16384 个哈希槽。
- 假设集群有 3 个主节点(A、B、C),这 16384 个槽会被平分给它们(比如 A 负责 0-5000,B 负责 5001-10000...)。
- 当客户端要写入一个 key 为
user:1的数据时,Redis 会计算CRC16("user:1") % 16384得到一个槽位号(比如 6000),然后发现 6000 这个槽位在 B 节点上,客户端就会把数据直接发给 B 节点。
- 高可用保障:每个主节点自身还可以挂载从节点(比如一主一从,3个主就是6台机器)。如果 A 节点挂了,它的从节点 A1 会自动升级为新的主节点接管槽位,这就是 Cluster 自带的高可用机制(不需要额外再部署哨兵组)。
🌟 面试加分项(实战坑点探讨): 面试官可能会问:"如果我有个超级热点新闻的数据(比如 key 为 news:hot:1),被分配到了 A 节点。结果几百万并发全部打向这个单一节点,Cluster 集群能抗住吗?" 绝杀回答: "抗不住。这就是 Cluster 集群最怕的数据倾斜/热点 Key 问题。不管你集群有几百台机器,根据 Hash 算法,这个特定 Key 的请求全都会打在唯一的那台机器上。 怎么解决?
- 本地缓存(最有效):在 JVM 层面上加一层 Caffeine 或 Guava Cache,拦截掉 90% 的热点读请求。
- 复制多份热点数据:比如把原 Key 拼接上随机后缀(
news:hot:1_1、news:hot:1_2...),存多份到不同的节点。读取时客户端随机拼凑后缀去读,强行把单点读并发打散到整个集群。"
❓ 面试官:在主从复制或者集群发生脑裂(Split-Brain)时,会导致数据丢失吗?怎么解决?【高级】
频率:🔥🔥🔥
💡 一句话总结(先抛结论): 会。脑裂是指因为网络分区故障,导致同时出现了两个主节点,客户端还在不停地向“旧主节点”写入数据,当网络恢复后,“旧主节点”被降级为从节点并清空自己的数据去同步“新主节点”的数据,从而导致脑裂期间写入的数据全部丢失。
📝 详细原理解析:
脑裂场景重现:
- 机房网络波动,导致哨兵集群(或者 Cluster 其他节点)无法访问到现有的 Master(M1)。
- 哨兵们认为 M1 挂了,于是从剩下的 Slave 中选出了新的 Master(M2)。
- 但是!M1 并没有真正宕机,只是网络跟哨兵断了,它和客户端之间的网络依然是好的。
- 此时,客户端还在拼命地往 M1 写数据。
- 几分钟后,机房网络恢复。哨兵发现 M1 活了,强行把它降级为 M2 的从节点。
- 灾难降临:变成从节点的 M1 会立刻清空自己内存中的所有数据,去全量同步新主节点 M2 的数据。这几分钟内客户端往 M1 写的几十万条数据,瞬间灰飞烟灭。
如何防范脑裂数据丢失?:
- 配置 Redis 的两个参数:
bash
# 至少要求有 1 个从节点在线
min-replicas-to-write 1
# 主从节点之间的网络延迟不能超过 10 秒
min-replicas-max-lag 10
```
- **原理**:当网络发生分区,M1 失去与其他所有节点的联系时,它会发现自己没有任何一个从节点能正常通信(延迟超过10秒)。此时,M1 就会**直接拒绝客户端所有的写请求**(返回 Error)。
- **代价**:宁可牺牲部分可用性(这几分钟内系统不可写),也要保证数据的绝对安全性。