客户端连接集群

客户端连接集群

客户端连接集群的方式

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));

自动重连

当节点宕机或重启后,客户端需要自动重建连接:

  1. 检测连接断开(IOException)
  2. 从槽位映射中移除不可达节点
  3. 尝试重新连接或通过其他节点刷新映射

最大重试次数

// 设置最大 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)可以大大简化集群连接的开发工作。

© 版权声明
THE END
喜欢就支持一下吧
点赞11 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容