Skip to content
hashkey.bond

Archivehashing

Consistent Hashing Without the Hand-Waving

Virtual nodes, and why the ring is really a weighted random assignment that happens to be cheap to update.

Published
Reading time
1 min read

Place nodes on a hash ring, hash a key onto the same ring, walk clockwise to the first node: that is consistent hashing. Its value is not the ring — it is that adding or removing a node moves only 1/n of the keys, instead of reshuffling everything.

Virtual nodes are the actual design

One point per physical node gives terrible balance: with 10 nodes, the expected max share can be several times the mean. Give each node 100–200 virtual positions and the load concentrates near 1/n.

for i in range(vnodes):
    ring[hash(f"{node}:{i}")] = node

Replication is just the next r distinct physical nodes clockwise.

The traps

  • Key-to-node maps still need a stable hash across clients; a per-process seed means clients disagree about placement.
  • Hot keys are not fixed by the ring — one key always lands on one node.
  • Rebalancing after a node join is 1/n of keys, but that can still be terabytes; move data incrementally.

Takeaway: consistent hashing minimizes movement, not imbalance. Virtual nodes handle the balance; replication handles failures; neither handles hot keys.