Weighted jump consistent hash: what works

Weighted jump consistent hash is not a mode built into Jump Hash. The original function accepts a key and a count of equal buckets. It has no weight input and returns one sequential bucket number.

You can still put weights around it. The useful version hashes into stable logical buckets, then maps those buckets to physical nodes in proportion to capacity. That extra map changes the movement guarantee.

Use logical buckets for small, stable integer ratios. Use weighted rendezvous hashing when weights change independently or nodes must disappear in any order.

Weighted jump consistent hash starts with equal buckets

The Jump Hash paper defines a function of a 64-bit key and num_buckets. Its output is an integer from 0 through num_buckets minus one.

Each bucket receives about 1/N of the keys. When bucket N is appended, about 1/(N + 1) of all keys move to it, and keys do not move between the old buckets.

That result depends on two constraints. Bucket IDs fill one consecutive range, and every bucket has the same target share.

A physical node with twice the capacity of another node does not fit either input. Passing two copies of its name is impossible because Jump Hash sees numbers, not names.

This limitation is easy to miss because ring hashing often uses virtual nodes for both smoothing and weights.

Fanout's consistent hashing guide explains the ring model before comparing it with other placement functions.

Put a logical-bucket map after Jump Hash

Suppose nodes A, B, and C have capacity weights 1, 2, and 3. Create six logical buckets and assign one to A, two to B, and three to C.

Jump Hash chooses a number from 0 through 5. A small lookup table then converts that logical bucket into a physical node.

The expected physical shares are 1/6 for A, 2/6 for B, and 3/6 for C. Jump Hash still balances keys evenly across the six logical buckets.

This construction is often called shadow nodes. Several logical bucket IDs resolve to one physical destination.

The method is exact for integer ratios. A 2:3 capacity ratio needs five logical buckets. A 10:15 ratio reduces to the same five after dividing by the greatest common divisor.

Fractions need a chosen resolution. Weights 1.00, 1.25, and 1.75 become 4:5:7 at quarter-unit precision, which requires 16 logical buckets.

More precision creates more buckets and a larger owner map. Jump lookup remains small, but placement metadata and migration planning no longer have zero cost.

The movement guarantee stops at the logical layer

Jump Hash minimizes movement when the logical bucket count grows by appending sequential IDs. It does not know that several logical IDs point to one physical node.

If the owner of logical bucket 4 changes from B to C, every key assigned to bucket 4 moves. Jump Hash returns the same result as before; the indirection table changed underneath it.

The distinction matters during a weight update. Changing 1:2:3 into 2:5:6 requires 13 logical buckets if the ratio must be exact.

Appending seven buckets preserves Jump Hash's logical monotonicity. It does not automatically minimize physical movement because the order and owners of those new buckets determine which nodes gain keys.

Rebuilding the six old assignments is worse. Any old logical bucket whose owner changes moves its entire 1/6 share, even if a smaller set of keys could have produced the new physical ratio.

Treat the logical-bucket table as versioned placement metadata. Measure movement between versions at the physical-node level rather than by counting changed Jump Hash outputs alone.

Stable shard IDs make the wrapper useful

The wrapper works best when logical buckets are durable shards rather than disposable server entries.

Each shard ID can have replicas and a current owner. A failed machine changes the placement record for affected shards, while the key-to-shard function stays fixed.

This matches the storage model in the original paper. Jump Hash assumes shards do not simply vanish. Replication or replacement handles failure, and capacity changes adjust the sequential shard set.

The LavinMQ migration note shows the membership tradeoff.

Its exchange distributes messages across queues, where membership behavior is part of the public contract.

LavinMQ kept ring hashing as the default because switching algorithms changes assignments. Better balance inside the new algorithm does not make a placement migration free.

For a storage service, keep three concepts separate: the stable shard number, the physical owner, and the capacity policy that assigns shard owners.

Fanout's distributed systems labs guide is a good continuation if you want to test those layers under node changes instead of stopping at a hash-function example.

Weighted rendezvous handles changing weights directly

Weighted rendezvous hashing scores every candidate node for the key and chooses the highest score. The node ID is part of the score, so arbitrary names and removals are natural.

The weighted score can be written as negative w divided by log u, where w is the node weight and u is a uniform hash value between zero and one.

The current IETF weighted HRW draft explains why multiplying a normalized weight by a raw hash is not enough.

Normalizing by the sum of all weights changes every node's factor when one weight changes. That can move keys between two nodes whose own weights did not change.

With the negative w over log u score, changing one node's weight changes only that node's score. It can win or lose keys, while the ordering among unchanged nodes remains intact.

The result is minimum movement back to the new weighted equilibrium because no keys transfer between two unchanged nodes.

The cost is lookup work. Plain rendezvous evaluates every candidate, so lookup time grows with the number of nodes. Jump Hash reaches one logical bucket in logarithmic expected time with constant working memory.

Do not confuse capacity weight with current load

A capacity weight is a slow placement input: disk size, memory, link bandwidth, or an agreed service tier. It says what share a node should own over many keys.

Current queue depth and CPU utilization change much faster. Feeding them straight into a consistent-hash weight can create continuous remapping and destroy cache locality.

For request routing, use a stable hash to choose a small candidate set, then apply a live load-aware policy inside that set. For durable data, move shards through an explicit migration controller.

Weights also need one unit. Mixing disk bytes for one node with measured requests per second for another produces ratios with no physical meaning.

Record the weight source, precision, update threshold, and minimum time between placement versions. A mathematically stable scoring function cannot protect an unstable control loop.

Choose the wrapper from the change pattern

Use Jump Hash plus logical buckets when all four conditions hold:

  • Logical shard IDs are stable and sequential.
  • Capacity ratios are small integers or tolerate coarse rounding.
  • Weight changes are rare and planned.
  • Replication handles physical node failure.

Use weighted rendezvous when nodes have arbitrary IDs, weights change independently, or removing one failed node must not renumber the rest.

Use a weighted ring when an existing ecosystem already depends on ring order and its virtual-node metadata is acceptable. Assigning more virtual nodes to a larger machine approximates its capacity share.

Whatever you choose, test two quantities separately: final key share per physical node and keys moved between placement versions.

Weighted jump consistent hash is a two-layer design, not a new hash formula. Jump chooses equal logical buckets. Your placement layer supplies weights and owns the consequences when they change.