Chapter 21 · Redis Cluster: Hash Slots, Routing, Resharding, and Cluster Availability
16384 Hash Slots, CRC16, Key Distribution, Nodes, Primaries, Replicas, and Cluster Bus
Build the slot-level mental model for Redis Cluster, including CRC16, hash tags, shards, replicas, topology APIs, and the private Cluster bus.
Learning outcomes
By the end of this lesson, you should be able to:
Explain why Redis Cluster partitions the keyspace into exactly 16,384 hash slots rather than hashing keys directly to a permanent node.
Calculate and verify slot placement with CRC16 modulo 16,384 and the hash-tag exception.
Read CLUSTER INFO, CLUSTER SHARDS,
and CLUSTER NODES as different views of one
topology.
Distinguish client port 6379 from the node-to-node Cluster bus and explain primary/replica shard membership.
Create a reproducible six-node Cluster without exposing Cluster ports to the host network.
Redis Open Source 8.10.1 using
redis:8.10.1; seven named containers are defined
but the normal cluster starts six nodes (three primaries + three
replicas) on private Docker network
atlasmart-redis-ch21-net; the seventh node is
started only for add/remove exercises; Redis Cluster uses
logical database 0 only; AOF everysec;
maxmemory 0/noeviction for this
bounded lab; TLS is off only because all Cluster client/bus
traffic is confined to one private single-host Docker network;
default ACL user is disabled; named
academy-admin and atlasmart-app users
use disposable lab passwords. No
Search/JSON/vector/time-series/probabilistic feature is
required. All keys use atlasmart:ch21:*.
1. Practical problem: one primary cannot scale every AtlasMart key
AtlasMart now has carts, inventory, sessions, and ranking keys whose combined working set and request rate no longer fit one Redis primary comfortably. Redis Cluster solves this by partitioning key ownership across multiple primaries while retaining replicas for failover. The unit of placement is not “a server” but a hash slot.
A slot is a numbered bucket in the range 0–16383. A primary owns a set of slots; every key maps to exactly one slot; therefore moving slot ownership can move data responsibility without changing the key itself.
2. Exact slot formula: CRC16 modulo 16,384
For an ordinary key Redis Cluster computes the XMODEM CRC16
checksum and keeps 14 effective bits by applying modulo 16,384.
The formula is HASH_SLOT = CRC16(key) mod 16384.
The important operational consequence is that nodes can be added
or removed by transferring slot ranges instead of changing a
consistent-hash ring.
docker exec -e REDISCLI_AUTH=AtlasMart-Ch21-Admin-Lab-Only-2026 atlasmart-redis-ch21-n1 \ redis-cli --user academy-admin CLUSTER KEYSLOT atlasmart:ch21:product:1001docker exec -e REDISCLI_AUTH=AtlasMart-Ch21-Admin-Lab-Only-2026 atlasmart-redis-ch21-n1 \ redis-cli --user academy-admin CLUSTER KEYSLOT atlasmart:ch21:cart:{customer-42}:lines
3. Hash tags change what gets hashed
If a key contains a valid non-empty
{...} substring, only the substring between the
first valid brace pair is hashed. That lets related keys
intentionally share one slot. It is a locality tool, not a free
performance trick: putting every AtlasMart key under one tag
would collapse a sharded cluster back into one hot slot.
| Key | Hashed material | Design implication |
|---|---|---|
| atlasmart:ch21:cart:{customer-42}:lines | customer-42 | Can share multi-key operations with same tag |
| atlasmart:ch21:cart:{customer-42}:meta | customer-42 | Same slot as lines |
| atlasmart:ch21:cart:{customer-99}:meta | customer-99 | Normally different slot |
| atlasmart:ch21:product:1001 | whole key | Naturally distributed |
4. Node, shard, primary, replica, and Cluster bus
A node is one Redis server participating in the Cluster gossip protocol. A shard is one primary plus the replicas that replicate that primary and serve the same slots. Nodes exchange failure, slot, epoch, and topology information over the Cluster bus, distinct from normal RESP client traffic. In the default TCP layout the bus port is derived from the client port; this lab keeps both private inside Docker.
5. Build the private seven-service lab definition
The normal topology starts only n1–n6. n7 exists in the Compose file but remains stopped until Lesson 4. Use at least about 1 GB of free RAM and 1 GB of free disk for a comfortable single-host exercise; smaller machines can reduce dataset volume because correctness does not depend on a large dataset.
name: atlasmart-redis-ch21x-node: &node image: redis:8.10.1 restart: "no" networks: [cluster] volumes: - ./users.acl:/usr/local/etc/redis/users.acl:ro command: ["redis-server","--port","6379","--cluster-enabled","yes","--cluster-config-file","nodes.conf","--cluster-node-timeout","5000","--cluster-preferred-endpoint-type","hostname","--appendonly","yes","--appendfsync","everysec","--save","300","10","--aclfile","/usr/local/etc/redis/users.acl","--masteruser","academy-admin","--masterauth","AtlasMart-Ch21-Admin-Lab-Only-2026","--cluster-slot-stats-enabled","yes"]services: n1: <<: *node container_name: atlasmart-redis-ch21-n1 hostname: atlasmart-redis-ch21-n1 command: ["redis-server","--port","6379","--cluster-enabled","yes","--cluster-config-file","nodes.conf","--cluster-node-timeout","5000","--cluster-announce-hostname","atlasmart-redis-ch21-n1","--cluster-preferred-endpoint-type","hostname","--appendonly","yes","--appendfsync","everysec","--save","300","10","--aclfile","/usr/local/etc/redis/users.acl","--masteruser","academy-admin","--masterauth","AtlasMart-Ch21-Admin-Lab-Only-2026","--cluster-slot-stats-enabled","yes"] volumes: ["./users.acl:/usr/local/etc/redis/users.acl:ro","n1:/data"] n2: <<: *node container_name: atlasmart-redis-ch21-n2 hostname: atlasmart-redis-ch21-n2 command: ["redis-server","--port","6379","--cluster-enabled","yes","--cluster-config-file","nodes.conf","--cluster-node-timeout","5000","--cluster-announce-hostname","atlasmart-redis-ch21-n2","--cluster-preferred-endpoint-type","hostname","--appendonly","yes","--appendfsync","everysec","--save","300","10","--aclfile","/usr/local/etc/redis/users.acl","--masteruser","academy-admin","--masterauth","AtlasMart-Ch21-Admin-Lab-Only-2026","--cluster-slot-stats-enabled","yes"] volumes: ["./users.acl:/usr/local/etc/redis/users.acl:ro","n2:/data"] n3: <<: *node container_name: atlasmart-redis-ch21-n3 hostname: atlasmart-redis-ch21-n3 command: ["redis-server","--port","6379","--cluster-enabled","yes","--cluster-config-file","nodes.conf","--cluster-node-timeout","5000","--cluster-announce-hostname","atlasmart-redis-ch21-n3","--cluster-preferred-endpoint-type","hostname","--appendonly","yes","--appendfsync","everysec","--save","300","10","--aclfile","/usr/local/etc/redis/users.acl","--masteruser","academy-admin","--masterauth","AtlasMart-Ch21-Admin-Lab-Only-2026","--cluster-slot-stats-enabled","yes"] volumes: ["./users.acl:/usr/local/etc/redis/users.acl:ro","n3:/data"] n4: <<: *node container_name: atlasmart-redis-ch21-n4 hostname: atlasmart-redis-ch21-n4 command: ["redis-server","--port","6379","--cluster-enabled","yes","--cluster-config-file","nodes.conf","--cluster-node-timeout","5000","--cluster-announce-hostname","atlasmart-redis-ch21-n4","--cluster-preferred-endpoint-type","hostname","--appendonly","yes","--appendfsync","everysec","--save","300","10","--aclfile","/usr/local/etc/redis/users.acl","--masteruser","academy-admin","--masterauth","AtlasMart-Ch21-Admin-Lab-Only-2026","--cluster-slot-stats-enabled","yes"] volumes: ["./users.acl:/usr/local/etc/redis/users.acl:ro","n4:/data"] n5: <<: *node container_name: atlasmart-redis-ch21-n5 hostname: atlasmart-redis-ch21-n5 command: ["redis-server","--port","6379","--cluster-enabled","yes","--cluster-config-file","nodes.conf","--cluster-node-timeout","5000","--cluster-announce-hostname","atlasmart-redis-ch21-n5","--cluster-preferred-endpoint-type","hostname","--appendonly","yes","--appendfsync","everysec","--save","300","10","--aclfile","/usr/local/etc/redis/users.acl","--masteruser","academy-admin","--masterauth","AtlasMart-Ch21-Admin-Lab-Only-2026","--cluster-slot-stats-enabled","yes"] volumes: ["./users.acl:/usr/local/etc/redis/users.acl:ro","n5:/data"] n6: <<: *node container_name: atlasmart-redis-ch21-n6 hostname: atlasmart-redis-ch21-n6 command: ["redis-server","--port","6379","--cluster-enabled","yes","--cluster-config-file","nodes.conf","--cluster-node-timeout","5000","--cluster-announce-hostname","atlasmart-redis-ch21-n6","--cluster-preferred-endpoint-type","hostname","--appendonly","yes","--appendfsync","everysec","--save","300","10","--aclfile","/usr/local/etc/redis/users.acl","--masteruser","academy-admin","--masterauth","AtlasMart-Ch21-Admin-Lab-Only-2026","--cluster-slot-stats-enabled","yes"] volumes: ["./users.acl:/usr/local/etc/redis/users.acl:ro","n6:/data"] n7: <<: *node container_name: atlasmart-redis-ch21-n7 hostname: atlasmart-redis-ch21-n7 command: ["redis-server","--port","6379","--cluster-enabled","yes","--cluster-config-file","nodes.conf","--cluster-node-timeout","5000","--cluster-announce-hostname","atlasmart-redis-ch21-n7","--cluster-preferred-endpoint-type","hostname","--appendonly","yes","--appendfsync","everysec","--save","300","10","--aclfile","/usr/local/etc/redis/users.acl","--masteruser","academy-admin","--masterauth","AtlasMart-Ch21-Admin-Lab-Only-2026","--cluster-slot-stats-enabled","yes"] volumes: ["./users.acl:/usr/local/etc/redis/users.acl:ro","n7:/data"]networks: cluster: name: atlasmart-redis-ch21-netvolumes: {n1: {}, n2: {}, n3: {}, n4: {}, n5: {}, n6: {}, n7: {}}
user default offuser academy-admin on >AtlasMart-Ch21-Admin-Lab-Only-2026 ~* &* +@alluser atlasmart-app on >AtlasMart-Ch21-App-Lab-Only-2026 ~atlasmart:ch21:* &* +@read +@write +@connection +cluster|shards +cluster|slots +cluster|keyslot
6. Start six nodes and create three shards
Create the Docker network and six processes first, then use the
pinned redis-cli inside n1 to allocate all 16,384 slots across
three primaries and assign one replica to each primary. The
order passed to --cluster create makes n1–n3 the
initial primary candidates; always verify the resulting replica
pairing rather than assuming it.
docker compose -f ch21-compose.yaml up -d n1 n2 n3 n4 n5 n6docker exec -e REDISCLI_AUTH=AtlasMart-Ch21-Admin-Lab-Only-2026 atlasmart-redis-ch21-n1 \ redis-cli --user academy-admin --cluster create \ atlasmart-redis-ch21-n1:6379 atlasmart-redis-ch21-n2:6379 atlasmart-redis-ch21-n3:6379 \ atlasmart-redis-ch21-n4:6379 atlasmart-redis-ch21-n5:6379 atlasmart-redis-ch21-n6:6379 \ --cluster-replicas 1 --cluster-yes
7. Observe three complementary topology views
CLUSTER INFO answers whether the local node
considers the cluster operational and whether all slots are
assigned/healthy. CLUSTER SHARDS is the preferred
modern client topology API since Redis 7.
CLUSTER NODES exposes node IDs, flags, config
epochs, link state, bus endpoint, slot ranges, and migration
markers. CLUSTER SLOTS remains available but has
been deprecated since Redis 7.
docker exec -e REDISCLI_AUTH=AtlasMart-Ch21-Admin-Lab-Only-2026 atlasmart-redis-ch21-n1 redis-cli --user academy-admin CLUSTER INFOdocker exec -e REDISCLI_AUTH=AtlasMart-Ch21-Admin-Lab-Only-2026 atlasmart-redis-ch21-n1 redis-cli --user academy-admin CLUSTER SHARDSdocker exec -e REDISCLI_AUTH=AtlasMart-Ch21-Admin-Lab-Only-2026 atlasmart-redis-ch21-n1 redis-cli --user academy-admin CLUSTER NODES
8. Expected evidence and its limits
A healthy baseline should show cluster_state:ok,
cluster_slots_assigned:16384, three primaries
serving slots, and three replicas attached to those primaries.
That proves current topology/coverage. It does not prove
fault-domain independence: all six containers still share one
host, Docker daemon, storage device, and power source.
9. Version-aware observability: per-slot statistics
Redis 8.2 introduced CLUSTER SLOT-STATS. This lab
enables slot statistics so you can rank slots by key count, CPU,
network bytes, and—on current Redis—memory bytes. This is
stronger evidence than counting slots per node because a node
with 5,000 mostly-cold slots can still be less loaded than one
with a single extremely hot slot.
docker exec -e REDISCLI_AUTH=AtlasMart-Ch21-Admin-Lab-Only-2026 atlasmart-redis-ch21-n1 \ redis-cli --user academy-admin CLUSTER SLOT-STATS ORDERBY KEY-COUNT LIMIT 10 DESCdocker exec -e REDISCLI_AUTH=AtlasMart-Ch21-Admin-Lab-Only-2026 atlasmart-redis-ch21-n1 \ redis-cli --user academy-admin CLUSTER SLOT-STATS ORDERBY CPU-USEC LIMIT 10 DESC
10. Deliberately wrong model: node count equals zone safety
Six processes on one laptop can teach Cluster algorithms but do not provide six independent failure domains. Production placement must consider hosts, racks/zones, power/network domains, disk, and client reachability. A replica on the same failed host as its primary contributes almost no host-failure protection.
Check your understanding
- Why does Redis Cluster use slots between keys and nodes?
- What formula maps an ordinary key to a slot?
- Why prefer CLUSTER SHARDS in new client/topology code?
- Does cluster_state:ok prove zone redundancy?
Review the answers
Slots provide a stable partitioning layer that can be reassigned during scale/failover without changing each key name.
XMODEM CRC16 of the key modulo 16384.
It is the extensible topology API introduced in Redis 7 and replaces deprecated CLUSTER SLOTS.
No. It proves current cluster health from that node’s perspective, not physical failure-domain placement.
11. Production judgment and bridge
Redis Cluster is appropriate when one logical Redis dataset needs horizontal key partitioning and clients can route by slot. It does not provide arbitrary cross-slot transactions or hide network topology. Capacity planning must include per-primary working set, replicas, failover headroom, reshard traffic, AOF/persistence, Cluster bus traffic, and client topology refresh. Lesson 2 turns routing failures into observable MOVED/ASK behavior.
Summary and next step
16384 Hash Slots, CRC16, Key Distribution, Nodes, Primaries, Replicas, and Cluster Bus is now connected to observable Redis behavior, bounded failure cases, and production tradeoffs. Keep the evidence and cleanup state from this lesson; next, continue with MOVED vs ASK Redirections, Cluster-Aware Clients, Topology Refresh, and Retry Behavior.
Authoritative references
- Redis Cluster specification
- Scale with Redis Cluster
- CLUSTER SHARDS
- CLUSTER SLOTS — deprecated since 7.0
- CLUSTER INFO
- CLUSTER NODES
- CLUSTER KEYSLOT
- CLUSTER SETSLOT
- CLUSTER MIGRATION
- CLUSTER SLOT-STATS
- CLUSTER FAILOVER
- ASKING
- MIGRATE
- Redis 8.10 release notes
- Redis 8.10 — what is new
- redis-py — connect to Redis Cluster
- redis-py 8.1.0 cluster documentation