Consistent hashing primer
Consistent hashing distributes keys across a dynamic pool of nodes so that adding or removing a node only reshuffles a small fraction of keys. Meridian uses it for shard routing in the gateway and for cache affinity in the reactor tier.
1.The ring abstraction
Imagine a circular keyspace from 0 to 2^32 - 1. Each node is hashed to a point on the ring, and each key is hashed to its own point. A key is owned by the first node found clockwise from its position. When a node leaves, only its successor inherits the keys.
2.Virtual nodes for balance
A single point per node leaves load imbalanced. Each physical node registers V virtual replicas (typically 100 to 200) at independent ring positions. The variance of keys per node falls as 1 / sqrt(V), which converges fast.
3.A minimal implementation
The reference implementation below uses a sorted ring of (position, node) pairs and a binary search to locate the owner for any key.
import { createHash } from 'crypto';
export class Ring {
private points: Array<[number, string]> = [];
add(node: string, vnodes = 128) {
for (let i = 0; i < vnodes; i++) {
const h = this.hash(`${node}#${i}`);
this.points.push([h, node]);
}
this.points.sort((a, b) => a[0] - b[0]);
}
owner(key: string): string {
const h = this.hash(key);
for (const [p, n] of this.points) {
if (p >= h) return n;
}
return this.points[0][1];
}
private hash(s: string): number {
const d = createHash('md5').update(s).digest();
return d.readUInt32BE(0);
}
}