Redis集群中的Hash Slot分配与数据迁移过程
Redis集群通过将数据拆分并存储在多个节点上,实现了水平扩展。这种数据分片的机制被称为Hash Slot(哈希槽)。掌握槽位的分配逻辑与数据迁移的具体步骤,是维护高可用Redis集群的核心技能。
一、 理解Hash Slot的分配原理
Redis集群预设了 16384 个槽位。集群中的每一个键值对都属于这 16384 个槽位中的某一个。数据并不是直接绑定在节点IP上,而是绑定在槽位上,槽位再分配给具体的节点。
当客户端读写数据时,集群会根据键名计算出一个数值,以决定该数据去往哪个节点。计算公式如下:
$$ \text{Slot ID} = \text{CRC16}(\text{key}) \pmod{16384} $$
这意味着:
- 一致性:同一个键名计算出的槽位编号永远相同。
- 分散性:足够多的键名会均匀地覆盖所有槽位。
为了实现负载均衡,槽位通常被均匀地分配给集群中的主节点。例如,在一个包含3个主节点的集群中,理想的分配状态如下表所示:
| 节点标识 | 负责的槽位范围 | 槽位数量 |
|---|---|---|
| Master A | 0 - 5460 | 5461 |
| Master B | 5461 - 10922 | 5462 |
| Master C | 10923 - 16383 | 5461 |
二、 准备工作:获取节点ID
在进行任何槽位迁移之前,必须获取源节点(迁出方)和目标节点(迁入方)的ID。
连接 到集群中的任意一个节点,执行 命令:
redis-cli -c -p 7000 cluster nodes
查看 输出结果,找到对应IP地址和端口的长字符串ID(类似 3c3a0c74aae0b82b4323c5a2f8a6b7c8),并记录下来。假设源节点ID为 <source_id>,目标节点ID为 <target_id>。
三、 数据迁移的核心流程
手动迁移槽位是一个非常精细的过程,主要分为四个阶段:标记、迁移、指派、广播。为了保证数据不丢失且服务不中断,必须严格按照顺序执行。
以下是迁移逻辑的流程图,展示了节点间如何协作完成槽位交接:
四、 实操步骤:手动迁移单个槽位
假设我们要将槽位 1000 从源节点迁移到目标节点。
1. 标记目标节点(准备导入)
连接 到目标节点,执行 IMPORTING 命令。这告诉目标节点:“我准备接收槽位 1000 的数据了,如果源节点发来数据,请收下”。
redis-cli -c -p 7001 CLUSTER SETSLOT 1000 IMPORTING <source_id>
2. 标记源节点(准备导出)
连接 到源节点,执行 MIGRATING 命令。这告诉源节点:“我准备把槽位 1000 移交出去,如果客户端访问该槽位且Key不存在,告诉它去目标节点找”。
redis-cli -c -p 7000 CLUSTER SETSLOT 1000 MIGRATING <target_id>
3. 获取槽位内的Key列表
连接 到源节点,查询 槽位 1000 中目前有多少个键。COUNT 参数指定一次返回的键数量(此处设为10)。
redis-cli -c -p 7000 CLUSTER GETKEYSINSLOT 1000 10
该命令会返回该槽位下的键名列表,例如 key1, user:1001 等。
4. 迁移键数据
对上一步获取到的每一个键,执行 MIGRATE 命令。这个命令会将键从源节点原子性地移动到目标节点。
redis-cli -c -p 7000 MIGRATE <target_ip> 6379 <key_name> 0 5000
<target_ip>:目标节点的IP地址。6379:目标节点端口。<key_name>:具体的键名。0:表示不超时(或指定超时时间)。5000:表示如果有多个相关键(如哈希结构的字段),也一并复制。
重复 步骤3和步骤4,直到 CLUSTER GETKEYSINSLOT 返回空列表,表示该槽位下的所有数据已搬空。
5. 确认槽位归属
当源节点槽位为空后,需要在集群任意节点上执行 SETSLOT 命令的 NODE 子命令。这步操作会将槽位 1000 的所有权正式指派给目标节点,并向集群广播这一变更。
redis-cli -c -p 7000 CLUSTER SETSLOT 1000 NODE <target_id>
五、 批量迁移的高效方法
手动逐个迁移槽位效率极低且容易出错。Redis官方提供了内置工具 redis-cli 的 --cluster reshard 功能,可以自动化完成上述所有步骤。
打开 终端,运行 下面的命令:
redis-cli --cluster reshard <your_cluster_ip>:7000
工具会进入交互模式,按照 提示操作:
- 输入 要移动的槽位总数(例如 1000)。
- 输入 接收这些槽位的目标节点ID。
- 输入 源节点ID。如果想从所有其他节点各抽取一部分,输入
all。 - 输入
yes确认 执行计划。
工具会自动:
- 计算每个源节点需要迁出的槽位。
- 在后台执行
IMPORTING/MIGRATING标记。 - 批量移动键数据。
- 更新集群配置并广播。
六、 迁移过程中的客户端行为
在槽位迁移期间,客户端可能会遇到两类重定向指令,理解它们的区别有助于排查问题:
- MOVED 重定向:表示槽位已经明确不属于当前节点,且已经完成了归属权变更。客户端必须更新本地缓存,后续请求直接发送给新节点。
- ASK 重定向:仅在迁移期间出现。表示“槽位还在我这里,但你要找的那个Key刚搬到隔壁了”。客户端需要在下一次请求前发送
ASKING命令,然后尝试去目标节点读取。客户端不应更新本地槽位缓存,因为下一次请求可能还要找源节点。

暂无评论,快来抢沙发吧!