关于 redis-clustering
为 Redis Cluster 分片及独立主从部署提供键设计和读流量路由指南,重点讲解如何避免 CROSSSLOT 错误,并利用副本承接读请求,同时考虑最终一致性。
主要功能
- 01用哈希标签支持多键操作
- 02将读请求路由到副本
- 03主从节点路由指南
- 04副本一致性权衡说明
适用场景
- 01为 Redis Cluster 设计键
- 02排查 CROSSSLOT 错误
- 03不增加分片来扩展读流量
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ redis/ agent-skills --skill redis-clustering安装后在 Claude Code 中输入/redis-clustering确认已加载。
附带文件references/hash-tags.mdreferences/read-replicas.md
详细介绍
Redis 集群
关于在分片 Redis Cluster(以及独立主节点/副本复制)中设计键和路由读取的指南。涵盖大多数新集群用户容易遇到的两种故障模式:多键操作出现 CROSSSLOT 错误,以及主节点因读取流量过大而过载。
适用场景
- 为 Redis Cluster 部署设计键。
- 排查
MGET、SDIFF、事务或管道操作中的CROSSSLOT错误。 - 实现会操作多个键的事务 / Lua 脚本。
- 无需添加分片即可扩展读取流量。
1. 多键操作的哈希标签
Redis Cluster 通过对键名进行哈希,将键分配到 16,384 个槽位中。任何操作多个键的命令(MGET、SDIFF、SUNIONSTORE、事务、管道操作、含有多个 KEYS[] 的 Lua 脚本)都要求所有键位于同一个槽位,否则服务端会返回 CROSSSLOT 错误。
哈希标签可以强制实现这一点:{ 和 } 之间的部分是槽位分配时唯一参与哈希的内容,因此共享同一哈希标签的两个键总会落在同一个槽位。
# Same slot — multi-key ops work
redis.set("{user:1001}:profile", "...")
redis.set("{user:1001}:settings", "...")
redis.lmove("{user:1001}:pending", "{user:1001}:processed", "LEFT", "RIGHT")
# Different keys, no hash tag — CROSSSLOT on multi-key commands in cluster mode
redis.set("user:1001:profile", "...")
redis.set("user:1001:settings", "...")
pipe = redis.pipeline()
pipe.get("user:1001:profile")
pipe.get("user:1001:settings")
pipe.execute() # CROSSSLOT error in cluster
经验法则:
- 使用限定在有意义实体范围内的标签,例如
{user:1001}。避免使用{1001}这样的裸标签——不相关的命名空间(purchase:{1001}、employee:{1001})都会冲突在同一个槽位。 - 只在确实需要多键操作时添加标签。 给所有键都添加标签会造成热点,违背分片的初衷。
- 带哈希标签的键照常支持单键命令,因此之后添加标签也可以逐步进行;但在生产环境中重命名键很麻烦,所以应提前规划好需要分组的实体标签。
2. 面向读取密集型工作负载的只读副本
如果读取量远高于写入量,可将读取请求路由到副本,以释放主节点容量。在 Redis Cluster(每个分片有 1 个或多个副本)和独立主节点/副本复制中都适用。
# Redis Cluster: enable replica reads on the client
from redis.cluster import RedisCluster
rc = RedisCluster(host="localhost", port=6379, read_from_replicas=True)
rc.set("key", "value") # → primary
value = rc.get("key") # → may be served by a replica
对于非集群设置,将两个客户端分别指向相应节点:
primary = Redis(host="primary-host", port=6379)
replica = Redis(host="replica-host", port=6379)
primary.set("key", "value")
value = replica.get("key")
需要权衡的是一致性:副本最终会保持一致。不要从副本读取自己刚写入的数据;对于要求严格实时性的场景(金融余额、幂等性状态),不要使用副本读取。适用场景包括:缓存层、分析、仪表板、推荐信息流。
参见 references/read-replicas.md。
参考资料
评论
支持 Markdown