mcpField
R
redis-clustering

redis-clustering

github.com/redis数据与数据库1711.8k 次安装7 周前更新
代码仓库

关于 redis-clustering

为 Redis Cluster 分片及独立主从部署提供键设计和读流量路由指南,重点讲解如何避免 CROSSSLOT 错误,并利用副本承接读请求,同时考虑最终一致性。

主要功能

  1. 01用哈希标签支持多键操作
  2. 02将读请求路由到副本
  3. 03主从节点路由指南
  4. 04副本一致性权衡说明

适用场景

  1. 01为 Redis Cluster 设计键
  2. 02排查 CROSSSLOT 错误
  3. 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})都会冲突在同一个槽位。
  • 只在确实需要多键操作时添加标签。 给所有键都添加标签会造成热点,违背分片的初衷。
  • 带哈希标签的键照常支持单键命令,因此之后添加标签也可以逐步进行;但在生产环境中重命名键很麻烦,所以应提前规划好需要分组的实体标签。

参见 references/hash-tags.md。

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