redis-clustering
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseRedis Clustering
Redis集群
Guidance for designing keys and routing reads in a sharded Redis Cluster (and in standalone primary/replica replication). Covers the two failure modes that bite most new cluster users: errors on multi-key operations, and overloading primaries with read traffic.
CROSSSLOT为分片Redis Cluster(以及独立主从复制)中的键设计与读取路由提供指南。涵盖了大多数新集群用户常会遇到的两种故障模式:错误(多键操作时出现),以及主节点因读取流量过载的问题。
CROSSSLOTWhen to apply
适用场景
- Designing keys for a Redis Cluster deployment.
- Debugging a error on
CROSSSLOT,MGET, transactions, or pipelines.SDIFF - Implementing transactions / Lua scripts that touch multiple keys.
- Scaling out read traffic without adding shards.
- 为Redis Cluster部署设计键。
- 调试、
MGET、事务或管道中的SDIFF错误。CROSSSLOT - 实现涉及多个键的事务/Lua脚本。
- 在不添加分片的情况下扩展读取流量。
1. Hash tags for multi-key operations
1. 多键操作的哈希标签
Redis Cluster distributes keys across 16,384 slots by hashing the key name. Any command that touches multiple keys (, , , transactions, pipelines, Lua scripts with multiple ) requires all keys to live on the same slot — otherwise the server returns a error.
MGETSDIFFSUNIONSTOREKEYS[]CROSSSLOTHash tags force this: the part between and is the only thing hashed for slot assignment, so two keys sharing a hash tag always land together.
{}python
undefinedRedis Cluster通过对键名进行哈希计算,将键分布到16384个槽位中。任何涉及多个键的命令(、、、事务、管道、包含多个的Lua脚本)都要求所有键位于同一个槽位中——否则服务器会返回错误。
MGETSDIFFSUNIONSTOREKEYS[]CROSSSLOT哈希标签可以强制实现这一点:和之间的部分是唯一用于槽位分配的哈希对象,因此共享同一哈希标签的两个键始终会被分配到同一个槽位。
{}python
undefinedSame 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")
```pythonredis.set("{user:1001}:profile", "...")
redis.set("{user:1001}:settings", "...")
redis.lmove("{user:1001}:pending", "{user:1001}:processed", "LEFT", "RIGHT")
```pythonDifferent keys, no hash tag — CROSSSLOT on multi-key commands in cluster mode
不同键,无哈希标签——集群模式下多键命令会触发CROSSSLOT错误
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
Rules of thumb:
- **Use a tag scoped to the meaningful entity**, e.g. `{user:1001}`. Avoid bare `{1001}` — unrelated namespaces (`purchase:{1001}`, `employee:{1001}`) would all collide on the same slot.
- **Only tag where you actually need multi-key ops.** Tagging everything creates hotspots and defeats the point of sharding.
- A single-key command on a hash-tagged key works fine, so adding tags later is incremental — but renaming keys in production is painful, so plan tagging up front for entities you'll group.
See [references/hash-tags.md](references/hash-tags.md).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错误
经验法则:
- **使用针对有意义实体的标签**,例如`{user:1001}`。避免使用无上下文的`{1001}`——不同命名空间(`purchase:{1001}`、`employee:{1001}`)会全部碰撞到同一个槽位。
- **仅在实际需要多键操作时添加标签**。给所有键添加标签会造成热点问题,违背分片的初衷。
- 带哈希标签的键的单键命令可正常执行,因此后续添加标签是增量式的——但在生产环境中重命名键非常麻烦,因此需要提前为需要分组的实体规划标签。
参见 [references/hash-tags.md](references/hash-tags.md)。2. Read replicas for read-heavy workloads
2. 面向读密集型工作负载的读取副本
If reads dominate writes, route them to replicas to free primary capacity. Works both in Redis Cluster (each shard has 1+ replica) and in standalone primary/replica replication.
python
undefined如果读取操作远多于写入操作,可将读取请求路由到副本以释放主节点的容量。这在Redis Cluster(每个分片有1个或多个副本)和独立主从复制中均适用。
python
undefinedRedis Cluster: enable replica reads on the client
Redis Cluster:在客户端启用副本读取
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
For non-cluster setups, point two clients at the right nodes:
```python
primary = Redis(host="primary-host", port=6379)
replica = Redis(host="replica-host", port=6379)
primary.set("key", "value")
value = replica.get("key")The trade-off is consistency: replicas are eventually consistent. Don't read your own writes from a replica; don't use replica reads for anything that requires strict freshness (financial balances, idempotency state). Good fits: cache layers, analytics, dashboards, recommendation feeds.
See references/read-replicas.md.
from redis.cluster import RedisCluster
rc = RedisCluster(host="localhost", port=6379, read_from_replicas=True)
rc.set("key", "value") # → 主节点
value = rc.get("key") # → 可能由副本提供服务
对于非集群部署,可将两个客户端分别指向对应节点:
```python
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。