客户端连接集群
客户端连接集群的方式
Redis Cluster 的客户端连接方式与单机 Redis 有显著不同。由于数据分散在多个节点上,客户端需要实现智能路由才能高效地访问数据。
客户端类型
1. Smart Client(智能客户端)
智能客户端在本地缓存集群的槽位映射表,能够直接计算出 Key 所在的节点并建立连接。这是推荐的生产环境连接方式。
工作流程:
连接任意节点
↓
执行 CLUSTER SLOTS 或 CLUSTER NODES
↓
获得完整槽位映射表
↓
缓存到本地(Map<SlotRange, Node>)
↓
每个请求:计算 CRC16(key) % 16384 → 查缓存 → 直连目标节点
主流 Smart Client:
| 语言 | 客户端 | 说明 |
|---|---|---|
| Java | JedisCluster | 最成熟,功能完整 |
| Java | Lettuce | 异步/响应式支持好 |
| Python | redis-py-cluster | Python 生态首选 |
| Go | go-redis | 支持集群模式 |
| Node.js | ioredis | 原生支持 Cluster |
2. 普通 Client + 代理
对于不支持 Cluster 的普通客户端,可以通过代理层连接:
客户端 → [代理层(Twemproxy / Codis / HAProxy)] → Redis Cluster
代理层处理槽路由和数据分片,对客户端透明。
3. 直连模式(不推荐)
手动连接集群中的特定节点。需要客户端自行处理 MOVED 重定向。仅用于测试或简单的管理操作。
连接初始化
引导节点(Bootstrap Node)
客户端只需要知道集群中任意一个节点的地址,就可以通过它获取整个集群的拓扑信息:
// JedisCluster 示例:只需要一个节点的地址
Set<HostAndPort> nodes = new HashSet<>();
nodes.add(new HostAndPort("192.168.1.1", 6379));
JedisCluster cluster = new JedisCluster(nodes);
获取槽位映射
初始化时,客户端通过 CLUSTER SLOTS 命令获取槽位信息:
CLUSTER SLOTS
1) 1) (integer) 0 // 起始槽
2) (integer) 5460 // 结束槽
3) 1) "192.168.1.1" // 主节点 IP
2) (integer) 6379 // 主节点端口
3) "abc123..."
4) 1) "192.168.1.2" // 从节点 IP
2) (integer) 6379
3) "def456..."
请求路由与重定向
正常情况(槽位命中)
客户端计算槽位后直接连接到正确的节点,一次网络往返完成请求。
MOVED 重定向(永久迁移)
SET user:1001 "Alice"
→ 节点 A 返回: -MOVED 7256 192.168.1.3:6379
客户端处理:
1. 更新本地缓存:槽 7256 → 节点 C
2. 重新发送请求到节点 C
ASK 重定向(临时迁移)
GET user:1001
→ 返回: -ASK 7256 192.168.1.3:6379
客户端处理:
1. 不更新缓存(ASK 是临时行为)
2. 先向节点 C 发送 ASKING 命令
3. 再发送 GET user:1001
ASK vs MOVED 的本质区别:
– MOVED:槽已永久迁移,客户端应更新缓存
– ASK:槽正在迁移中,仅当前 Key 可能已被迁移
连接管理优化
连接池
Smart Client 通常会为每个节点维护独立的连接池:
// 每个节点一个连接池
Map<String, JedisPool> connectionPools = new HashMap<>();
connectionPools.put("192.168.1.1:6379", new JedisPool(config, "192.168.1.1", 6379));
connectionPools.put("192.168.1.2:6379", new JedisPool(config, "192.168.1.2", 6379));
自动重连
当节点宕机或重启后,客户端需要自动重建连接:
- 检测连接断开(IOException)
- 从槽位映射中移除不可达节点
- 尝试重新连接或通过其他节点刷新映射
最大重试次数
// 设置最大 MOVED 重定向次数,防止无限循环
JedisCluster cluster = new JedisCluster(nodes, 5000, 5000, 5, "password");
// maxAttempts = 5
常见问题
1. 连接所有节点
连接集群时,客户端会连接所有槽位映射中的节点。如果集群有 100 个节点,客户端会建立 100 个连接。注意调整操作系统的文件描述符限制。
2. 节点变更通知
当集群拓扑发生变化(增加/删除节点、重新分片)时:
– Smart Client 会在收到 MOVED 时更新局部缓存
– 定期(每隔几秒)重新拉取 CLUSTER SLOTS 刷新全量缓存
3. Pipeline 跨节点限制
Pipeline 中的命令如果涉及多个节点,需要按节点分组发送,不能一次发送跨节点的 Pipeline。
总结
客户端连接 Redis Cluster 的核心是 Smart Client 模式——通过缓存槽位映射实现高效路由,通过 MOVED/ASK 机制处理拓扑变化。理解重定向机制和连接池管理是生产环境中稳定使用 Redis Cluster 的基础。选择合适的客户端库(如 JedisCluster、Lettuce、ioredis)可以大大简化集群连接的开发工作。


暂无评论内容