Partitioning: consistent hashing and hash slots
The primer’s three ways to spread a cache, why mod N remaps most keys, libketama’s ring with many points per server, and Redis Cluster’s 16,384 slots.
What you will learn
- Compare a cache per machine, a copy on every machine and a sharded cache.
- Explain why hash mod moves almost every key when a server fails.
- Map keys with a Ketama ring and with Redis Cluster's 16,384 hash slots.
Spreading the cache over many machines
The primer lists three options once one machine is not enough:
- Each machine has its own cache. Simple, "although it will likely result in a low cache hit rate".
- Each machine has a copy of the cache. Simple, but "an inefficient use of memory".
- Shard the cache across machines. More complex, but "likely the best option". Pick the machine with
machine = hash(query), and preferably consistent hashing.
Why not hash mod N?
spreads keys evenly, but changing moves almost everything. When one server of 10 fails, a key stays put only if , which is true for 1 key in 10. So 90% of keys move to a different server and miss at once. Adding 2 servers to 10 moves about 83% of keys.
Consistent hashing
libketama, the Memcached client library from Last.fm, describes the method:
- "Hash each server string to several (100-200) unsigned ints". These points sit on a circle "that goes from 0 to 2^32".
- "To map a key->server, hash your key to a single unsigned int, and find the next biggest number on the continuum." Past the last point, wrap to the first.
- "If you then add or remove a server from the list, only a small proportion of keys end up mapping to different servers." A new server takes keys only from the arcs where its points land: about of all keys, and every moved key moves to the new server.
- Servers can be weighted "by adding more or less points to the continuum", for example in proportion to memory.
Why many points per server. With one point each, arc lengths vary widely. In the visual's measurements, the busiest of 4 servers holds about 1.9 times its fair share, and with 10 servers about 3.7 times. With 100 to 200 points per server, the busiest holds within about 4–13% of its fair share.
Redis Cluster: 16,384 hash slots
Redis Cluster does not use a ring. Its specification:
- Each primary owns a set of slots. Resharding moves whole slots between nodes.
- Hash tags: if a key contains
{…}with something inside, only that part is hashed.{user:1001}.profileand{user:1001}.ordersland in the same slot, so multi-key commands work across them. - The spec reports that "CRC16 behaved remarkably well in distributing different kinds of keys evenly across the 16384 slots".
The routing visual (lesson 4) computes real slots with Redis's CRC16.
A consistent-hash ring
Each server is hashed to several points on a 0 to 2³² circle; a key belongs to the next point clockwise. Counts below use 5,000 sample keys.
Key takeaways
- Sharding the cache is the most complex option and usually the best; hash mod moves 90% of keys when one of 10 servers fails.
- Ketama hashes each server to 100–200 points on a circle; a key belongs to the next point, so adding or removing a server moves only about of the keys (the new server's fair share when one is added).
- With one point per server the load is uneven; many points even it out, and weighting points lets bigger servers take more.
- Redis Cluster maps keys to CRC16 mod 16,384 slots and moves whole slots; hash tags keep related keys in one slot.
Sources
- System Design Primer: Design a key-value cache, scaling the design
- libketama README (consistent hashing for Memcached clients)
- Redis Cluster specification
Adapted from The System Design Primer by Donne Martin, licensed under CC BY 4.0. Changes were made.