Mind and Hand Help

Routing in Distributed Systems

question

分布式系统中的路由有谁来负责?客户端还是服务端?

answer

两种方式都存在,要看具体系统的设计选择

客户端路由 client-side routing

客户端自己决定请求发到哪个节点,例如

  • 通过一致性哈希(Consistent Hashing)或某种分片规则定位到具体节点

  • 通常客户端会缓存一份集群拓扑信息或元数据

代表系统:

  • Cassandra

  • Riak

  • Kafka Producer(可以自己决定发送到哪个 partition)

优点:

  • 请求路径短,直接到目标节点

  • 减少跳转、中间层压力

缺点:

  • 客户端实现复杂,要感知集群拓扑变化

  • 拓扑变化(比如扩容)可能导致客户端缓存失效,需要有刷新机制

服务端路由 server-side routing

客户端只连接某个入口节点(称为 router、coordinator、proxy 等),再由这个节点在集群内部路由转发。

代表系统:

  • MongoDB(mongos)

  • TiDB(SQL 层接入)

  • HBase(通过 RegionServer)

  • Elasticsearch(coordinating node)

优点:

  • 客户端简单,不需要关心数据分布

  • 系统可以集中处理元数据、负载均衡

缺点:

  • 增加一跳,可能引入性能瓶颈

  • 入口节点成为潜在的热点或单点故障点(需高可用设计)

对比例子

Kafka(客户端路由):

Kafka 的 producer 会从 broker 获取元数据,然后根据 topic 的 partition 和 key 做 hash,直接发送消息到对应的 broker。这样中间没有 proxy,性能高。

MongoDB(服务端路由):

MongoDB 分片集群中,客户端连接 mongos,而不是直接连接 shard。mongos 是查询协调器,接收请求后根据 chunk 的分布信息,分发请求到对应 shard 上。

Redis Cluster

数据分片

  • Redis Cluster 将整个 key 空间划分为 16384 个 slot(称为 哈希槽)。

  • 每个 key 通过 CRC16(key) % 16384得到其 slot 编号。

  • 每个节点负责其中的一部分 slot。

路由流程(客户端侧):

  1. 客户端第一次连接时 ,会从任意一个 Redis 节点获取集群拓扑信息(即所有 slot 分布在哪些节点)。

  2. 计算 slot :发送命令时,客户端根据 key 计算它属于哪个 slot。

  3. 选择节点 :根据 slot 到节点的映射,直接将命令发送到对应的节点。

如果客户端路由错了(比如映射信息过期),Redis 节点会返回:

  • -MOVED :告诉客户端该 slot 已经迁移到其他节点,客户端需更新 slot 映射表。

  • -ASK :表示 slot 正在迁移过程中,客户端暂时重定向到新节点(但不更新本地映射)。

客户端需要支持这类重试和 slot 映射更新逻辑。

Redis Cluster 节点如何管理 slot?

Redis Cluster 将 16384 个 slot 显式分配给集群中的节点。每个节点会维护一份 slot -> 节点 的映射信息,并参与集群协议,确保这个映射在整个集群中是一致的。

一、slot 是怎么分配给节点的?

在 Redis Cluster 启动或扩容时,管理员手动(或使用工具如 redis-cli --cluster create)将 slot 分配给节点。比如:

  • 节点 A:0 ~ 5460

  • 节点 B:5461 ~ 10922

  • 节点 C:10923 ~ 16383

Redis 每个主节点(master)会维护自己负责的 slot 范围,并在 CLUSTER SLOTS、CLUSTER NODES 等命令中向外暴露这些信息。

二、slot 元数据存储在哪?

每个 Redis 节点内部维护一张哈希表:

struct clusterNode { int slots[16384]; // 每个节点记录自己负责哪些 slot }

此外,每个节点还记录所有其他节点的 IP、端口、角色(master/slave)、健康状态等集群元数据。

三、节点之间如何同步 slot 信息?

Redis Cluster 节点通过 gossip 协议(定期交换心跳包和元数据)相互同步 cluster 状态,包括:

  • 每个节点负责的 slot 范围

  • 节点是否宕机

  • 主从关系是否发生切换

slot 是否在迁移(migrating/importing)

这些信息帮助节点共同维持整个集群的一致视图。

四、slot 迁移是怎么进行的?(Re-sharding)

当你想把部分 slot 从节点 A 移动到节点 B:

  1. 设置状态标志:

  • A 设置 slot 为 migrating

  • B 设置该 slot 为 importing

  1. 通过 CLUSTER SETSLOT 命令通知集群 slot 状态变化

  2. 搬迁数据:

  • 客户端或管理员使用 redis-cli --cluster reshard 工具

  • 将指定 slot 上的 key 从 A 拉到 B,通常用 MIGRATE 命令实现

  1. 完成后 slot 属于 B,更新集群状态

客户端这时会收到 ASK 响应,提示临时重定向请求到目标节点。

五、如何查看 slot 分布?

# 查看 slot -> 节点映射 redis-cli -c -h 任意节点 cluster slots # 查看节点视图(包含每个节点管理的slot) redis-cli -c -h 任意节点 cluster nodes

总结对比

方式

特点

代表系统

客户端路由

高性能、需要客户端维护路由信息

Cassandra、Kafka、Couchbase

服务端路由(代理)

简化客户端逻辑、可集中控制负载,但增加中间跳转

MongoDB、TiDB、HBase、ES

27 January 2026