Step 1 of 5 · Reading · ~3 min
Read
Production
Putting It All Together
You have built every piece of a consistent-hashing router separately. In this lesson you assemble them into one program: a weighted ring that places keys, lists replicas, changes weights, and reports exactly which keys move when membership changes.
| Piece | Where you built it |
|---|---|
Why modulo fails, the K/N goal | Why Consistent Hashing? |
| Clockwise successor with wrap-around | The Hash Ring |
| Many points per node, a hash that mixes | Virtual Nodes |
| Who moves when membership changes | Rebalance on Add/Remove |
| Points proportional to weight, gradual drain | Weighted Ring |
| Preference lists of distinct nodes | Replication on the Ring |
The result is the same feature set as memcached's ketama ring (weights included) plus the replication rule that Cassandra and Riak layer on top of theirs.
One structure, four rules
The program keeps one sorted list of (position, node) entries and a record of each node's point count. Everything else is a rule applied to that list.
- Placement. A node of weight
wplaces128 * wpoints ath32(name + "#" + i). A key belongs to the first entry at or afterh32(key), wrapping at the end. - Replication. Walk clockwise from the key and collect distinct node names. Weights never enter the walk: a heavy node is the primary more often, but it appears at most once in any list.
- Reweighting.
SETWEIGHTremoves the node's points and places new ones with the same labels, which gives the same ring as if the node had been added with that weight. - Measuring. Track a set of keys, change something, then diff the owners.
Here is the measurement on a ring that none of the earlier lessons used: P (weight 1), Q (3), R (1), S (2), with 4,000 tracked keys. Lowering Q to weight 1 and then raising it to 3 again:
SETWEIGHT Q 1 SETWEIGHT Q 3
Q -> P: 217 P -> Q: 217
Q -> R: 276 R -> Q: 276
Q -> S: 455 S -> Q: 455
moved=948/4000 moved=948/4000
Every key that moved left Q on the way down and returned on the way up, because the labels are the same both ways. The ring holds 896 points (7 units of weight times 128).
Composition traps
Removal must erase every point. A weight-2 node owns 256 points. Leave one behind and it still wins lookups for its arc, which is why POINTS is in the command set.
A node with weight 0 is still a node. It has no points, so it is never a primary or a replica, but WEIGHTS, LOAD and SPREAD list it with a zero. A ring where every weight is 0 answers NONE.
The default weight is 1. A bare ADD_NODE A places 128 points, not zero and not a crash. Adding a name that exists changes nothing and prints EXISTS, even if a different weight is given.
Unknown names. REMOVE_NODE and SETWEIGHT on a name that is not on the ring print UNKNOWN.
What separates this from production
A real hash (MD5 or MurmurHash3 across the whole key), persistence of ring state across restarts, rack-aware replica placement, streaming of data alongside ownership, and agreement between clients (gossip or a config service) so that every client builds the same ring. Without that last item two clients route the same key to different owners.
The next three lessons replace the ring when its trade-offs pinch: jump hash (no memory, buckets numbered 0..N-1), Maglev (a precomputed table for line-rate lookups) and bounded loads (the ring plus a hard cap per node). The ring with vnodes stays the right default because it handles named nodes, arbitrary adds and removes, weights and replication with a single structure.
Your exercise
The starter gives you h32 and the command loop. You implement the ring, the replica walk, the reports and the diff, using what the previous lessons taught.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…