报错是这么冒出来的。Redis 7.2 三主三从集群,批量取用户画像用 mget user:1:profile user:2:profile,客户端抛 CROSSSLOT Keys in request don't hash to the same slot,单条 get 正常,改成 pipeline 也没有改善。

中间走过弯路,把「客户端库在集群模式下把 mget 原样转发,没有自动拆分」当成主因,改完现象没变。

排查方向其实有限,先把可能性排一排。集群按 key 的哈希分片,mget 里多个 key 落在不同 slot 无法一次执行。少数情况下是key 没有用 hash tag 固定到同一 slot。

不容易想到的是,事务里混用了多个不同前缀的 key。

算几个 key 分别落在哪个 slot

redis-cli -c cluster keyslot user:1:profile; redis-cli -c cluster keyslot user:2:profile

再往下用 hash tag 把同组 key 固定到一个 slot

redis-cli -c cluster keyslot user:{8821}:profile

接着改成分组批量取或逐条 pipeline

python -c "import redis;r=redis.RedisCluster(host='10.0.0.11',port=6379);p=r.pipeline();[p.get('user:%d:profile'%i) for i in (1,2,3)];print(p.execute())"

或者按 slot 分组后并发取

python -c "print({'group_by':'slot','batches':3})"

怎么算真的好了,看的是同一批现象。批量读取不再报 CROSSSLOT,返回顺序与请求一致,扩容后同样的调用仍然可用。

提醒一点。集群模式下的多 key 命令都受 slot 约束,hash tag 是最省事的解法,但它也会把数据集中到一个分片,容量要提前算。拖得越久,排查成本越高,因为现场状态会被后续操作覆盖。

作者 9823189