Claude Cursor Skill

redis-clustering

Redis Cluster and replication guidance covering hash tags for multi-key operations, avoiding CROSSSLOT errors, and reading from replicas to scale read-heavy workloads. Use when designing keys for a sharded Redis Cluster, debugging CROSSSLOT errors on MGET / SDIFF / pipelines, con

LLM Mart · 0 points · 15 views 48 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download redis-agent-skills-plugins_redis-development_skills_redis-clustering-172fb9e.zip · 3 KB
Part of redis/agent-skills — 12 skills

Install

skills CLI npx skills add https://github.com/redis/agent-skills/tree/main/plugins/redis-development/skills/redis-clustering
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install redis-agent-skills@llmmart
Git git clone https://github.com/redis/agent-skills.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole redis/agent-skills collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

Redis Clustering

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.

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.

1. Hash tags for multi-key operations

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.

# 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

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.

2. Read replicas for read-heavy workloads

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.

# 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

For non-cluster setups, point two clients at the right nodes:

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.

References

Files (agent-skills)
  • references
    • hash-tags.md 2.5 KB
      # Use Hash Tags for Multi-Key Operations
      
      In Redis Cluster, keys are distributed across slots based on their hash. Use hash tags to ensure keys that must be used together in [multi-key operations](https://redis.io/docs/latest/operate/rs/databases/durability-ha/clustering/#multikey-operations) are on the same slot.
      
      **Correct:** Use hash tags for keys used in multi-key operations.
      
      **Python** (redis-py):
      ```python
      # These keys go to the same slot because {user:1001} is the hash tag
      redis.set("{user:1001}:profile", "...")
      redis.set("{user:1001}:settings", "...")
      redis.set("{user:1001}:cart", "...")
      
      # Now you can use transactions and pipelines
      pipe = redis.pipeline()
      pipe.get("{user:1001}:profile")
      pipe.get("{user:1001}:settings")
      pipe.execute()
      
      # Multi-key commands also work
      redis.lmove("{user:1001}:pending", "{user:1001}:processed", "LEFT", "RIGHT")
      ```
      
      **Java** (Jedis):
      ```java
      import redis.clients.jedis.UnifiedJedis;
      import java.util.Set;
      
      try (UnifiedJedis jedis = new UnifiedJedis("redis://localhost:6379")) {
          // Hash tags ensure keys go to the same slot
          jedis.sadd("{bikes:racing}:france", "bike:1", "bike:2", "bike:3");
          jedis.sadd("{bikes:racing}:usa", "bike:1", "bike:4");
      
          // Multi-key operation works because of matching hash tags
          Set<String> result = jedis.sdiff("{bikes:racing}:france", "{bikes:racing}:usa");
      }
      ```
      
      **Incorrect:** Keys without hash tags that need multi-key operations.
      
      **Python** (redis-py):
      ```python
      # Bad: These may be on different slots
      redis.set("user:1001:profile", "...")  # No hash tag
      redis.set("user:1001:settings", "...")
      
      # This will fail in cluster mode
      pipe = redis.pipeline()
      pipe.get("user:1001:profile")
      pipe.get("user:1001:settings")
      pipe.execute()  # CROSSSLOT error
      ```
      
      **Java** (Jedis):
      ```java
      // Bad: No hash tags - keys may be on different slots
      jedis.sadd("bikes:racing:france", "bike:1", "bike:2", "bike:3");
      jedis.sadd("bikes:racing:usa", "bike:1", "bike:4");
      
      // This will fail in cluster mode with CROSSSLOT error
      Set<String> result = jedis.sdiff("bikes:racing:france", "bikes:racing:usa");
      ```
      
      **Hash tag rules:**
      - Only the part between `{` and `}` is hashed for slot assignment
      - Use meaningful identifiers like `{user:1001}` not just `{1001}` to avoid unrelated keys (e.g., `purchase:{1001}`, `employee:{1001}`) saturating the same slot
      - Use hash tags only where multi-key operations are needed, not as a general habit
      
      Reference: [Redis Cluster Key Distribution](https://redis.io/docs/latest/operate/oss_and_stack/reference/cluster-spec/#hash-tags)
      
    • read-replicas.md 1.2 KB
      # Use Read Replicas for Read-Heavy Workloads
      
      For read-heavy workloads, distribute reads across replicas to reduce load on primaries.
      
      **Correct:** Configure replica reads in Redis Cluster.
      
      ```python
      from redis.cluster import RedisCluster
      
      rc = RedisCluster(
          host='localhost',
          port=6379,
          read_from_replicas=True  # Distribute reads to replicas
      )
      
      # Writes go to primary
      rc.set("key", "value")
      
      # Reads can be served by replicas (eventually consistent)
      value = rc.get("key")
      ```
      
      **Correct:** Use replica reads in standalone replication setup.
      
      ```python
      from redis import Redis
      
      # Connect to primary for writes
      primary = Redis(host='primary-host', port=6379)
      
      # Connect to replica for reads
      replica = Redis(host='replica-host', port=6379)
      
      # Write to primary
      primary.set("key", "value")
      
      # Read from replica (eventually consistent)
      value = replica.get("key")
      ```
      
      **Considerations:**
      - Replica reads are eventually consistent
      - Don't read from replicas for data that was just written
      - Use for read-heavy, slightly-stale-OK workloads (caches, analytics, dashboards)
      
      Reference: [Redis Replication](https://redis.io/docs/latest/operate/oss_and_stack/management/replication/)
      
  • SKILL.md 4 KB
    ---
    name: redis-clustering
    description: Redis Cluster and replication guidance covering hash tags for multi-key operations, avoiding CROSSSLOT errors, and reading from replicas to scale read-heavy workloads. Use when designing keys for a sharded Redis Cluster, debugging CROSSSLOT errors on MGET / SDIFF / pipelines, configuring a multi-key transaction in a cluster, or routing reads to replicas for caches, analytics, or dashboards.
    license: MIT
    metadata:
      author: Redis, Inc.
      version: "0.1.0"
    ---
    
    # Redis Clustering
    
    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.
    
    ## 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.
    
    ## 1. Hash tags for multi-key operations
    
    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
    # 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
    # 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
    ```
    
    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).
    
    ## 2. Read replicas for read-heavy workloads
    
    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
    # 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
    ```
    
    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](references/read-replicas.md).
    
    ## References
    
    - [Redis Cluster spec — hash tags](https://redis.io/docs/latest/operate/oss_and_stack/reference/cluster-spec/#hash-tags)
    - [Redis: multi-key operations in cluster](https://redis.io/docs/latest/operate/rs/databases/durability-ha/clustering/#multikey-operations)
    - [Redis: Replication](https://redis.io/docs/latest/operate/oss_and_stack/management/replication/)
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related