Redis Cluster 集群
一、三种模式对比
| 模式 | 版本 | 优点 | 缺点 |
|---|---|---|---|
| 主从模式 | 2.8之前 | 数据备份、读写分离 | 无法自动故障转移、无法动态扩容 |
| 哨兵模式 | 2.8+ | 自动故障转移、主从切换 | 从节点下线无感知、master无法动态扩容 |
| Cluster 模式 | 3.0+ | 无中心化、水平扩展、自动故障转移、数据分片 | 架构较新、不支持多DB、批量操作受限 |
二、什么是 Redis Cluster?
-
由多个主从节点群组成的分布式集群
-
具备复制、高可用、分片特性
-
无中心节点(P2P 模式),通过 Gossip 协议通信
-
可水平扩展,官方建议不超过 1000 个节点
-
适用场景:海量数据 + 高并发 + 高可用
三、核心架构图
text
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Master1 │◄──►│ Master2 │◄──►│ Master3 │
│ Slot0- │ │ Slot- │ │ Slot- │
│ 5460 │ │ 10922 │ │ 16383 │
└────┬────┘ └────┬────┘ └────┬────┘
│ │ │
┌────┴────┐ ┌────┴────┐ ┌────┴────┐
│ Slave1 │ │ Slave2 │ │ Slave3 │
└─────────┘ └─────────┘ └─────────┘
-
每个节点之间相互连通
-
客户端连接任意节点即可访问整个集群
四、数据分片(Slot)
核心公式
text
HASH_SLOT = CRC16(key) % 16384
Slot 特点
-
固定 16384 个槽位(0 ~ 16383)
-
每个 Master 节点负责一部分 Slot
-
Slave 节点只负责使用,没有所有权
-
只有 Master 节点被分配 Slot
五、集群通信
1. 节点发现(MEET 命令流程)
text
Node A ──MEET──► Node B
Node A ◄──PONG── Node B
Node A ──PING──► Node B
之后通过 Gossip 协议传播给其他节点
2. Gossip 协议消息类型
| 消息 | 作用 |
|---|---|
| MEET | 新节点加入集群 |
| PING | 交换元数据,检测存活 |
| PONG | 对 PING/MEET 的响应 |
| FAIL | 广播节点宕机信息 |
六、请求重定向
| 错误类型 | 场景 | 客户端行为 |
|---|---|---|
| MOVED | key 的 Slot 不在当前节点 | 更新本地 Slot 映射,重试 |
| ASK | Slot 正在迁移,key 已移走 | 先发 ASKING,再发请求(不更新映射) |
七、故障转移
选举流程(基于 Raft)
-
从节点发现主节点下线
-
广播投票请求给所有有投票权的主节点
-
获得 ≥ N/2 + 1 票的从节点成为新主
-
一轮未选出则进入下一轮
故障转移步骤
-
选出一个从节点
-
执行
SLAVEOF NO ONE成为新主 -
接管原主节点的所有 Slot
-
广播 PONG 消息通知其他节点
-
开始处理请求
集群可用性配置
conf
cluster-require-full-coverage no # 部分 Slot 不可用时集群仍可用
八、数据迁移
Slot 迁移状态
| 状态 | 所在节点 | 行为 |
|---|---|---|
| MIGRATING | 源节点 | key 不存在时返回 ASK |
| IMPORTING | 目标节点 | 收到 ASKING 命令后才接受请求 |
迁移过程中的命令处理
-
单 key:存在则处理,不存在则返回 ASK
-
多 key:
-
全部存在 → 成功
-
全部不存在 → 返回 ASK
-
部分存在 → 返回 TRYAGAIN
-
九、健康检查机制
-
每个节点定期发送 PING,超时时间
node_timeout -
超时一半时间未回复,尝试重连
-
节点标记为 PFAIL(主观下线)
-
当大多数主节点 都认为某节点为 PFAIL 时,标记为 FAIL(客观下线)
-
触发故障转移
PFAIL → FAIL 的转换需要多数主节点确认,防止误判
十、使用注意事项
| 注意事项 | 说明 |
|---|---|
| Master 宕机恢复 | 不会自动切回主节点,需手动干预 |
| 扩容操作 | 命令复杂,容易出错或丢数据 |
| 从节点读取 | 需执行 readonly=yes,连接关闭后失效 |
| 启动方式 | 必须用绝对路径,否则 nodes.conf 会混乱 |
| 多 DB | 不支持,只能使用 0 号数据库,SELECT 命令禁用 |
十一、业务侧改造要点
| 操作类型 | 要求 | 示例 |
|---|---|---|
| 批量操作 | key 必须在同一 Slot | mset {user}:1001 name {user}:1001 age |
| 事务操作 | 所有 key 在同一 Slot | MULTI ... EXEC |
| Lua 脚本 | 所有 key 在同一 Slot | EVAL "..." 2 {user}:key1 {user}:key2 |
| Pipeline | 所有 key 在同一台 Server | 使用 JedisCluster 自动路由 |
| 代码依赖 | 改用 Cluster 客户端 | JedisCluster 替代 Jedis |
技巧 :使用
{固定前缀}包裹 key 的一部分,可确保这些 key 落在同一个 Slot
十二、总结对比
| 特性 | 主从 | 哨兵 | Cluster |
|---|---|---|---|
| 自动故障转移 | ❌ | ✅ | ✅ |
| 动态扩容 | ❌ | ❌ | ✅ |
| 无中心化 | ❌ | ❌ | ✅ |
| 数据分片 | ❌ | ❌ | ✅ |
| 批量操作支持 | ✅ | ✅ | 受限 |
| 多 DB 支持 | ✅ | ✅ | ❌ |