Consistent Hashing Explained: How a Hash Ring Keeps Your Cache Warm

Diagram of a consistent hashing ring with servers A, B and C and a key walking clockwise to its owning server

Consistent hashing is a way of deciding which server holds which key, built so that adding or removing a server moves only a small share of the keys. That one property makes it a core idea in caches, distributed databases and load balancers.

This guide builds the idea step by step without heavy maths. You'll see why the obvious approach, hash mod N, falls apart when servers change. Then you'll learn how a ring of hash values, a simple clockwise rule and virtual nodes fix the problem.

In short
  • Hash mod N ties every lookup to the server count, so changing N moves almost every key.
  • Consistent hashing places servers and keys on the same ring using one hash function.
  • Each key belongs to the first server found by walking clockwise from its position.
  • Adding or removing a server only affects keys in that server's slice of the ring.
  • Virtual nodes give each server many ring positions, which evens out load and softens failures.
  1. 0:00Intro
  2. 0:34More servers, slower site?
  3. 1:30Consistent hashing in one sentence
  4. 2:24The simple way: hash mod N
  5. 3:12Why mod N breaks
  6. 4:09Picture a ring of hash values
  7. 4:50Place servers and keys on it
  8. 5:49Walk clockwise to find the owner
  9. 6:39Add a server, move one slice
  10. 7:40Remove a server: neighbour takes over
  11. 8:35You'll meet it everywhere
  12. 9:29The shop sale, done right
  13. 10:17Skipping virtual nodes
  14. 11:10The fix: many virtual nodes
  15. 12:02Consistent hashing in five points
  16. 12:29Small changes, small reshuffles

Why can adding a cache server make a site slower?

Picture a busy shop website with a cache in front of its database. Traffic is climbing ahead of a big sale, so the team adds one more cache server. More capacity should mean faster answers. On the day the server goes in, though, things can get worse before they get better.

The cause is how keys are mapped to servers. If adding a server changes where most keys are looked up, requests go to servers that never stored those keys. The data still sits on the old servers, but nobody is asking them for it. Every server now looks empty for the keys it is being asked about.

A cache normally shields the database from most reads. When that shield drops all at once, every miss lands on the database together, and the database gets flooded. The extra server was meant to add headroom. Instead it triggered a wave of misses.

  • Cold cache: keys land on servers that never stored them.
  • Database overload: misses pile onto the database at the same moment.

What is consistent hashing?

Consistent hashing spreads keys across servers, like any sharding method. What sets it apart is how it reacts when the list of servers changes. When a server joins or leaves, only a small part of the key-to-server mapping changes. Most keys stay exactly where they were, so most of the cache stays warm.

Every key, such as a user ID or a page address, gets one clear home. Any client can work out that home by itself by running the same calculation. Nobody has to maintain a central table of where every key lives. The result is the speed of hashing with far less disruption when the cluster changes.

  • Small reshuffles: server changes move only a few keys.
  • Keys spread out: every key gets one clear home.
  • No central list: clients compute locations and agree without a lookup table.

Why does hash mod N break when servers change?

Most people start with hash mod N, where N is the number of servers. You turn the key into a number with a hash function, divide by N, and use the remainder as the server number. For example, if user:42 hashes to 1042 and there are 3 servers, 1042 mod 3 is 1, so the key goes to Server 1.

This is fast and fair, and every client gets the same answer. The weakness is that N is built into every lookup. If you add a fourth server, the same key now gives 1042 mod 4, which is 2. User:42 has moved, and so have most other keys. Servers 0, 1 and 2 lose keys they held and receive keys they have never seen, while Server 3 starts empty.

In general, going from N to N plus one servers moves about N out of every N plus one keys, which is nearly everything. Removing a server or having one crash changes N in the same way. With mod N, any change to the cluster turns into a cache-wide reshuffle.

How does the consistent hashing ring work?

The fix starts with a picture. Take every value your hash function can produce, from zero up to its largest number, and bend that line into a circle so the end joins the beginning. Like a clock face, where one follows twelve, the step after the largest hash value is zero again. The ring has no edge, and every position has a next position.

Next, put both servers and keys on the ring using the same hash function. A server gets its position by hashing something unique about it, such as its name or address. A key gets its position by hashing the key itself. Because one rule places everything, any client can draw the identical ring without asking anyone.

In a small example ring running from 0 to 99, Server A lands at 10, Server B at 45 and Server C at 80, and the key user:42 lands at 30. Notice that the gaps between servers differ in size. A good hash scatters positions, so uneven gaps are expected, and they matter later.

  • Same hash function: servers and keys share one coordinate system.
  • Positions look random: the arcs between servers come out different sizes.
# put servers on a small ring, 0 to 99
ring.add(hash("server-A"), "A") # at 10
ring.add(hash("server-B"), "B") # at 45
ring.add(hash("server-C"), "C") # at 80
# keys use the same hash
pos = hash("user:42") # at 30

How does a key find its server on the ring?

The lookup rule fits in one sentence: start at the key and walk clockwise until you reach a server. That server owns the key. There is no division and no counting of servers, only a search for the nearest server ahead of the key.

Using the example ring, user:42 hashes to position 30. Walking clockwise through 31, 32 and onward, the first server reached is Server B at 45, so the key is stored on B. Every client follows the same steps and reaches the same answer on its own.

The ring's wrap-around handles keys near the top. A key at position 90 walks past 99, wraps back to zero, and reaches Server A at 10. Because of this, every key always finds an owner, wherever it lands.

What happens when you add or remove a server?

Suppose a new Server D hashes to position 25, between A at 10 and B at 45. Keys from 11 to 25 used to walk clockwise to B. Now D is the first server they meet, so that slice moves from B to D. User:42 at 30 still walks past D to reach B, so it stays put. Servers A and C keep every key they had, and B keeps most of its own.

Removing a server follows the same rule, whether it is planned maintenance or a crash. If Server C at 80 disappears, the keys from 46 to 80 lose their home. They keep walking clockwise past 99, wrap to zero and reach Server A at 10, which inherits them. Everything on B stays where it was.

In both cases, only the neighbourhood of the changed server is affected. A failure costs you one server's worth of keys, not the whole cache, and adding capacity leaves most of the cache warm.

  • Add D at 25: only keys 11–25 move, from B to D.
  • Remove C at 80: keys 46–80 move on to A.
  • All other keys stay on the same server.

Where is consistent hashing used?

Consistent hashing appears wherever data or traffic is spread across machines that come and go. Amazon's Dynamo paper described placing storage nodes on a ring so nodes could join or leave without reshuffling all the data, and it inspired many later databases. Apache Cassandra builds on the same idea: each node owns ranges of ring positions called tokens, so adding a node moves only some ranges to it.

Load balancers use it to keep requests sticky. Hashing a user or URL onto the ring sends it to the same backend each time, and adding a backend shifts only a few users. Distributed caches, such as Memcached clusters, are the classic case, with the client hashing each key to pick a node.

Return to the shop sale, now with a consistent-hashing cache client. The web app asks for a product, and the client hashes the key onto the ring and walks clockwise to cache node A, B or C. When node D is added, only D's slice misses and reaches the database. The database sees a small, short bump while D fills up, instead of a flood.

Why do you need virtual nodes in consistent hashing?

The basic ring works, but with only one position per server, load is often far from even. It is tempting to think that hashed positions are automatically balanced. In practice, some servers end up guarding long stretches of the ring and others short ones, almost by luck.

This causes two problems. The server with the biggest arc fills its memory and evicts keys early, while the others sit half idle. And when a server dies, all its keys go to a single neighbour that may already be busy. Uneven arcs can turn one small failure into a chain reaction.

The standard fix is virtual nodes. Instead of hashing Server A once, you hash A-1, A-2 and so on, many times, and every point still belongs to the same real server. Many small arcs average out, the way many coin flips even out, so each server gets roughly a fair share. A failed server's keys scatter across many neighbours, and a bigger machine can simply be given more virtual nodes.

  • Hot server: the busiest node runs out of memory first.
  • Domino failures: one neighbour inherits a whole dead server's load.
  • Virtual nodes: many small arcs per server add up to fair shares.
  • Weighted servers: bigger machines get more points on the ring.

Key takeaways

  • Hash mod N reshuffles almost every key when the server count changes.
  • Servers and keys share one ring, placed by the same hash function.
  • A key belongs to the next server clockwise, with wrap-around past the top.
  • Adding or removing a server moves only the keys in its neighbourhood.
  • Virtual nodes even out load and spread a failed server's keys across many neighbours.

Frequently asked questions

What problem does consistent hashing solve?

It stops a change in the number of servers from moving almost every key. With hash mod N, adding one server reshuffles nearly the whole cache. Consistent hashing moves only the keys in the affected server's slice of the ring.

How is consistent hashing different from hash mod N?

Hash mod N divides by the server count, so every answer changes when the count changes. Consistent hashing places servers and keys on a ring and sends each key to the next server clockwise. The server count never appears in the lookup, so a change only affects neighbouring keys.

What happens to keys when a server in a hash ring fails?

The failed server's keys keep walking clockwise to the next server on the ring, which takes them over. Keys on every other server stay where they are. With virtual nodes, those keys spread across many neighbours instead of landing on one.

What are virtual nodes in consistent hashing?

Virtual nodes are extra ring positions for each real server, made by hashing names like A-1, A-2 and so on. Many small arcs per server balance the load far better than a single point. They also let you give larger machines more positions so they handle more keys.

Does consistent hashing need a central lookup table?

No. Every client uses the same hash function and the same clockwise rule, so each one can work out a key's server by itself. They all reach the same answer without asking a central service.

Which systems use consistent hashing?

Well-known examples include Amazon Dynamo, Apache Cassandra with its token ranges, distributed caches such as Memcached clusters, and load balancers that keep users sticky to a backend. It suits any system where machines are added, removed or fail over time.

Watch the full video on YouTube →

Souy Soeng

Souy Soeng

Hi there 👋, I’m Soeng Souy (StarCode Kh)
-------------------------------------------
🌱 I’m currently creating a sample Laravel and React Vue Livewire
👯 I’m looking to collaborate on open-source PHP & JavaScript projects
💬 Ask me about Laravel, MySQL, or Flutter
⚡ Fun fact: I love turning ☕️ into code!

Post a Comment

CAN FEEDBACK
Ad