CROSSSLOT 是什么
集群把键空间分片后,一条命令涉及的所有键必须落在同一个槽里,否则无法在单个节点上完成,服务端直接返回 CROSSSLOT 错误,提示这些键没有哈希到同一个槽。受影响的包括 MGET、MSET、SINTERSTORE、SUNION、重命名、事务 MULTI、以及 Lua 脚本中的所有键。解决办法只有两个:要么让相关键通过哈希标签落在同一槽,要么把多键操作拆成多次单键调用。
基本信息
| 报错文本 | CROSSSLOT Keys in request do not hash to the same slot |
|---|---|
| 触发条件 | 多键命令或事务、脚本中涉及跨槽的键 |
| 哈希标签 | 用 {} 包住参与计算的部分,如 {user1001}:profile |
| 标签规则 | 只取第一对花括号内的内容参与 CRC16 计算 |
| 验证工具 | CLUSTER KEYSLOT 逐个确认键的槽号 |
典型使用场景
- 按业务主体聚合键:把同一用户的多个键套上相同标签,使相关多键操作在集群下可用
- 重构既有单机应用:上线集群前先梳理所有多键命令,逐一决定改标签还是改为多次单键调用
- Lua 脚本迁移:脚本中涉及的键必须同槽,否则需要拆脚本或调整键命名
- 客户端批量优化:确认哪些批量操作能合并、哪些必须按槽拆分后并发发送
- 故障排查:业务报错里出现 CROSSSLOT 时,用 KEYSLOT 快速定位是命名问题还是设计问题
复现与验证
复现与验证
redis-cli -c -p 7000 MGET k1 k2
# (error) CROSSSLOT Keys in request do not hash to the same slot
redis-cli -p 7000 CLUSTER KEYSLOT user:1001 # 看键落在哪个槽
redis-cli -p 7000 CLUSTER KEYSLOT '{user1001}:profile'
redis-cli -p 7000 CLUSTER KEYSLOT '{user1001}:orders' # 与上一行槽号相同
redis-cli -c -p 7000 MGET '{user1001}:profile' '{user1001}:orders' # 同槽后可用两类解法对照
| 解法 | 适用情况 | 代价 |
|---|---|---|
| 哈希标签同槽 | 键之间确有业务关联,如一个用户的多类数据 | 标签粒度决定分片均匀度,粗标签会造成热点 |
| 拆成多次单键调用 | 键之间没有强关联,如批量取多个无关对象 | 往返次数增加,需要并发发送或管道化 |
| 业务层聚合 | 集合运算跨主体,如求两个大集合的交集 | 需把数据拉到应用侧计算,注意内存与耗时 |
| 改用单键结构 | 把多个小对象合并进一个 Hash 或 ZSet | 单键规模上升,注意编码阈值与阻塞时间 |
标签的取用规则:只有第一对花括号内的内容参与 CRC16 计算,{a}{b} 只按 a 计算,{} 空标签则按整键计算。团队必须约定唯一且语义明确的前缀,否则同一业务主体被写成不同标签,多键操作仍然失败。
把所有键都套上同一个标签,等于把集群退化成单槽单机:所有写入集中在一个节点,其他节点空转,扩容与故障转移都失去意义。标签的粒度应落在「需要一起操作的键集合」这一层级。