tools

Consistent Hashing Playground: Modulo Hashing Moves 83% of Keys When a Server Joins, Jump Hash 17%

Five cache servers share 100,000 keys. Traffic grows, and you add a sixth. With the obvious rule, hash the key and divide by the number of servers, 83% of the keys now belong somewhere else. Most of them move between servers that never changed. For a cache that’s a wave of misses landing on the database at once. For a store it’s a mountain of data copied across the network for no reason.

The fair share for a new sixth server is a sixth of the keys, 16.7%. Consistent hashing is the family of rules that move about that much and no more. The Consistent Hashing Playground puts four of them side by side: add or remove a server and it counts what moves, draws the ring, and shows how even the load stays.

The Consistent Hashing Playground after a sixth node joins five, with 20,000 keys: the hash ring with the keys that moved drawn larger, and a table where modulo hashing moved 83.5% of keys and the hash ring, rendezvous hashing and jump hash between 14% and 17%.

With 100,000 keys and five servers growing to six, the command-line version of the playground measured this:

Method Keys moved Moved between servers that stayed Busiest server, vs an even share
Modulo 83.3% 66,724 1.01×
Hash ring, 160 virtual nodes each 14.6% 0 1.14×
Rendezvous hashing 16.5% 0 1.01×
Jump hash 16.7% 0 1.01×

Four Ways to Place a Key

Modulo is the baseline: hash the key, divide by the number of servers, keep the remainder. It spreads load evenly and falls apart whenever the number of servers changes.

The hash ring places servers and keys on a circle, and each key belongs to the first server clockwise from it. A new server takes over just the stretch of circle in front of it. With one point per server, the stretches vary wildly in length: on 10 servers, the busiest held 2.84 times an even share. So each server gets many points, called virtual nodes. With 10 per server the busiest held 1.46 times its share, and with 160 it held 1.08 times. This is the scheme from Karger and others in 1997, and the one Amazon’s Dynamo paper made famous.

Rendezvous hashing scores every server for every key, by hashing the two together, and the highest score wins. It spreads keys evenly with no tuning at all and is simple to write, but it looks at every server for every key, which adds up with hundreds of servers.

Jump hash, from Lamping and Veach at Google in 2014, is a short loop that needs no memory and comes out almost perfectly even. Its catch is that servers are numbered buckets, so it can only add or drop the last one. That suits a fixed set of numbered shards. Servers that join and leave in any order need one of the other methods.

Where Redis and Valkey Fit

Redis and Valkey clusters use none of these four directly. They hash every key into one of 16,384 fixed slots and assign ranges of slots to servers, and moving slots between servers is an operation you run on purpose. That gets the same result, only the keys of the moved slots move, with the timing under your control. The Hash Slot Calculator shows which slot any key is in.

Consistent hashing is also a standard question in system design interviews, and the playground is a quick way to see the answer rather than recite it. Drop the virtual nodes to one and watch the ring’s load fall apart, then add them back.

The playground’s logic is one JavaScript file with no dependencies, open source under the Apache License 2.0. Its MurmurHash3 matches the Python mmh3 package on 10,000 strings, and its jump hash matches the code printed in the paper on 20,000 keys. The manual and the tests are in the ring folder on GitHub.