System Design — Rendezvous (HRW) Hashing
consistent-hashing uses a ring. Rendezvous hashing (highest random weight) reaches the same
goal with no ring and no virtual nodes: for a key, score every node and pick the best.
Adding or removing a node only moves the keys that node wins or loses.
solve(args, ops) builds new Router(nodes) — args = [nodes], a list of node names — and
replays ops:
route(key)— return the node with the highest score forkey, ornullif there are no
nodes. The score of a node is hash(node + ":" + key). On equal scores the node name that
sorts first (plain string order) wins.
add(node)/remove(node)— change the node set. Adding an existing node or removing an
unknown one changes nothing. Return nothing.
The hash is pinned so every language agrees (inputs are ASCII). Take the 32-bit FNV-1a
hash of the UTF-8 bytes (start at 2166136261; for each byte: h ^= byte; h = h * 16777619
modulo 2^32), then apply the murmur3 finalizer:
h ^= h >>> 16; h = h * 0x85ebca6b (mod 2^32); h ^= h >>> 13; h = h * 0xc2b2ae35 (mod 2^32); h ^= h >>> 16The result is an unsigned 32-bit number. In JavaScript use Math.imul and >>> 0: a plain *
would lose precision above 2^53.
Sample tests