redis-clustering

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Redis 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:
CROSSSLOT
errors on multi-key operations, and overloading primaries with read traffic.
为分片Redis Cluster(以及独立主从复制)中的键设计与读取路由提供指南。涵盖了大多数新集群用户常会遇到的两种故障模式:
CROSSSLOT
错误(多键操作时出现),以及主节点因读取流量过载的问题。

When to apply

适用场景

  • Designing keys for a Redis Cluster deployment.
  • Debugging a
    CROSSSLOT
    error on
    MGET
    ,
    SDIFF
    , transactions, or pipelines.
  • 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 (
MGET
,
SDIFF
,
SUNIONSTORE
, transactions, pipelines, Lua scripts with multiple
KEYS[]
) requires all keys to live on the same slot — otherwise the server returns a
CROSSSLOT
error.
Hash 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
undefined
Redis Cluster通过对键名进行哈希计算,将键分布到16384个槽位中。任何涉及多个键的命令(
MGET
SDIFF
SUNIONSTORE
、事务、管道、包含多个
KEYS[]
的Lua脚本)都要求所有键位于同一个槽位中——否则服务器会返回
CROSSSLOT
错误。
哈希标签可以强制实现这一点:
{
}
之间的部分是唯一用于槽位分配的哈希对象,因此共享同一哈希标签的两个键始终会被分配到同一个槽位。
python
undefined

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")

```python
redis.set("{user:1001}:profile", "...") redis.set("{user:1001}:settings", "...") redis.lmove("{user:1001}:pending", "{user:1001}:processed", "LEFT", "RIGHT")

```python

Different 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
undefined

Redis 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

References

参考资料