bigywater.tech
Redis · 68

Redis Cluster Slot 分布

Redis Cluster 不按节点分数据,而是先把整个键空间切成 16384 个槽,再把槽分给主库。所有关于「数据在哪」的问题,都是在问「这个槽在哪个节点上」。这篇从零搭一个 3 主 3 从的集群,看槽位怎么分配、怎么查询,并把 10 万个 key 写进去,量它们在槽和节点上的实际分布。

5461 / 5462 / 5461
16384 个槽在 3 个主库上的分配(create 命令自动均分)
33359 / 33289 / 33352
10 万个 key 在三个主库上的 DBSIZE
6.10(σ=2.76)
每个槽里 key 数的平均值(标准差)

建集群:槽位如何分配

实测 · 本机执行输出
   Master[0] -> Slots 0 - 5460
   Master[1] -> Slots 5461 - 10922
   Master[2] -> Slots 10923 - 16383
   Adding replica 127.0.0.1:7304 to 127.0.0.1:7300
   Adding replica 127.0.0.1:7305 to 127.0.0.1:7301
   Adding replica 127.0.0.1:7303 to 127.0.0.1:7302
   [OK] All 16384 slots covered.

redis-cli --cluster create 把 16384 个槽按顺序平均切成三段:0–5460、5461–10922、10923–16383(5461 + 5462 + 5461)。三个从库随机挂到三个主库下。(为了让从库快点同步,实验中的每个节点都设了 repl-diskless-sync-delay 0,默认是 5 秒。)

CLUSTER NODES

实测 · 本机执行输出
  b17c901b 127.0.0.1:7300   myself,master  主=-        epoch=1 槽=0-5460
  3625acd4 127.0.0.1:7301   master         主=-        epoch=2 槽=5461-10922
  3b88246a 127.0.0.1:7302   master         主=-        epoch=3 槽=10923-16383
  b9107523 127.0.0.1:7303   slave          主=3625acd4 epoch=2 槽=-
  24408076 127.0.0.1:7304   slave          主=3b88246a epoch=3 槽=-
  e1ff2e34 127.0.0.1:7305   slave          主=b17c901b epoch=1 槽=-

每个主库有各自的 epoch(1、2、3),槽位区间写在每个主库那一行;从库那一行的第四列是它主库的 ID。同一个集群里所有节点看到的这张表是一致的,--cluster check 的 All nodes agree about slots configuration 检查的就是这一点。

写入 10 万个 key

实测 · 本机执行输出
客户端总重定向次数:MOVED 0(客户端从一开始就有完整槽位表)
各主库 DBSIZE: {7300: 33359, 7301: 33289, 7302: 33352}  合计 100000

我的客户端用自己实现的 CRC16 先算出每个 key 的槽位,再发给对应的主库,10 万次写入 MOVED 为 0。三个主库的 DBSIZE 是 33359、33289、33352,合计 100000,几乎均分。这里的 key 是 user:0 到 user:99999,没有使用 hash tag(第 72 篇)。

CLUSTER SLOTS 与 CLUSTER SHARDS

实测 · 本机执行输出
  CLUSTER SLOTS  槽     0–5460  共 5461 个  主 127.0.0.1:7300  从 [7305]
  CLUSTER SLOTS  槽  5461–10922 共 5462 个  主 127.0.0.1:7301  从 [7303]
  CLUSTER SLOTS  槽 10923–16383 共 5461 个  主 127.0.0.1:7302  从 [7304]
  CLUSTER SHARDS 槽 0–5460:master@7300(online)  replica@7305(online)
  CLUSTER SHARDS 槽 5461–10922:master@7301(online)  replica@7303(online)
  CLUSTER SHARDS 槽 10923–16383:master@7302(online)  replica@7304(online)

我第一次查询时(集群刚建好、没有数据流过),CLUSTER SLOTS 只返回主库、没有从库;CLUSTER SHARDS 显示从库的 health 是 loading。写入数据之后,两者都变成「主 + 从(online)」。所以刚建好的集群里,从库可能暂时不出现在槽位表里——依赖 CLUSTER SLOTS 做读写分离的客户端要注意(我没有深究 loading 的判定规则,只观察到了这个现象)。

槽里的 key 分布

实测 · 本机执行输出
平均 6.10 个/槽,最小 0,最大 13,标准差 2.76(若是完全随机的泊松分布,标准差应约 2.47)
抽查 5 个槽(槽号, 自己算的 key 数, CLUSTER COUNTKEYSINSLOT): [(0, 7, 7), (5460, 7, 7), (5461, 4, 4), (10922, 3, 3), (16383, 5, 5)]

10 万个 key 分布在 16384 个槽里,平均每槽 6.10 个,最少 0、最多 13,标准差 2.76。如果 key 是完全随机地落到槽里,标准差应约 2.47;实际略大,说明这批规则的 key 名(user:数字)在槽里的分布比纯随机稍散——但整体仍然很均匀(最大 13 vs 平均 6.1)。抽查的 5 个槽,CLUSTER COUNTKEYSINSLOT 返回的数与我自己用 CRC16 算出来的完全一致。

check 的输出

实测 · 本机执行输出
  127.0.0.1:7300 (b17c901b...) -> 33359 keys | 5461 slots | 1 slaves.
  127.0.0.1:7302 (3b88246a...) -> 33352 keys | 5461 slots | 1 slaves.
  127.0.0.1:7301 (3625acd4...) -> 33289 keys | 5462 slots | 1 slaves.
  [OK] 100000 keys in 3 masters.
  6.10 keys per slot on average.
  >>> Performing Cluster Check (using node 127.0.0.1:7300)
  M: b17c901b5d2d24edfbf3cce1ca1e59cc6ef38969 127.0.0.1:7300
     slots:[0-5460] (5461 slots) master
     1 additional replica(s)
  S: b910752392a99299b28f8e06c8a327f88e241bba 127.0.0.1:7303
     slots: (0 slots) slave
     replicates 3625acd442688c68fb1aebb769a9f111085bf81b
  S: e1ff2e34b9e0538a57265b5a56d1505b387259d2 127.0.0.1:7305
     slots: (0 slots) slave
     replicates b17c901b5d2d24edfbf3cce1ca1e59cc6ef38969
  M: 3b88246a9e397542ef4b11f3fa0583038bda3a97 127.0.0.1:7302
     slots:[10923-16383] (5461 slots) master
     1 additional replica(s)
  S: 244080767126b4fe80176f73bc4644ef8bb6365c 127.0.0.1:7304
     slots: (0 slots) slave
     replicates 3b88246a9e397542ef4b11f3fa0583038bda3a97
  M: 3625acd442688c68fb1aebb769a9f111085bf81b 127.0.0.1:7301
     slots:[5461-10922] (5462 slots) master
     1 additional replica(s)
  [OK] All nodes agree about

--cluster check 汇总:每个主库的 key 数、槽数、从库数;「All 16384 slots covered」表示所有槽都有主库负责。

分步演示:16384 个槽与三个主库

Redis Cluster Slot 分布
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 / Redis 8.10.2 独立实例(本机回环端口,save 关闭),redis-cli 风格输出由自写的 RESP 客户端打印;计时用 time.perf_counter,数字每次运行会有小幅抖动。3 主 3 从,cluster-node-timeout 3000,repl-diskless-sync-delay 0(只为加快从库同步)
    • 没有验证:更大集群(几十个主库)的槽位分配与再平衡、槽位在多个 key 类型(hash tag、集合等)下的分布、从库 health 为 loading 的判定条件
    京ICP备2026067502号-1京公网安备11010502063487号