Ketama
Node.js hash ring implementation using libketama-like hashing
Install / Use
/learn @connor4312/KetamaREADME
ketama
Ketama is a JavaScript/TypeScript implementation of the libketama hash ring. The primary advantage of ketama-style hashing is that it reduces the amount of work which is shuffled to other servers when the hashring membership changes.
npm install --save ketama
Then hash things:
// alternatively: const { HashRing } = require('ketama');
import { HashRing } from 'ketama';
const ring = new HashRing();
ring.addNode('127.0.0.1'); // add with default weight
ring.addNode('127.0.0.2', 2); // weight of 2 = twice as likely to choose this one
export function onDoWork(input) {
// hashes the input and choses a server based on it:
const server = ring.getNode(input);
doWorkOn(server);
}
export function doWorkOnMultipleServers(input) {
// picks two "replica" servers from the ring to do work on
for (const server of ring.getNodes(input, 2)) {
doWorkOn(server);
}
}
Table of Contents
HashRing([nodes], [hashFunction])
Creates a new HashRing, optionally with the initial set of nodes. The nodes can be either a string, or an object with a string property "key" which will be used internally to hash against, for example:
new HashRing(['127.0.0.1', { key: '127.0.0.2', port: 1337 }]);
When giving the nodes in the constructor, you can specify a weight by providing an object with the node and its weight. Weights are proportional; a node with a weight of 2 is twice as likely to be chosen than one with the default weight of 1. For example:
new HashRing([
{ node: '127.0.0.1', weight: 2 },
{ node: { key: '127.0.0.2', port: 1337 }, weight: 3
]);
Finally, you can also specify the hashing function to use. This can be either the name of an algorithm the require('crypto').createHash implements, or a custom function that returns an int32 given a Buffer. Defaults to sha1. For example:
new HashRing([], 'md5'); // hash with md5 instead
new HashRing([], buf => myCustomHash().readInt32BE()); // custom function
hashRing.addNode(node[, weight])
Adds a new node to the existing hashring. The node can be either a string, or an object with a string property "key" which will be used internally to hash against.
ring.addNode('127.0.0.1');
ring.addNode({ key: '127.0.0.2', port: 1337 });
You can optionally specify a weight as the second argument. Weights are proportional; a node with a weight of 2 is twice as likely to be chosen than one with the default weight of 1.
If the node already exists, it is replaced; for example, you can call addNode multiple times to update a node's weight.
hashRing.removeNode(node)
Removes a node previously added to the hash ring.
ring.removeNode('127.0.0.1');
No-op if the node is not in the ring.
hashRing.getNode(input)
Gets the node on which work should be done for the given input, which should be either a string or buffer. Returns the object or string originally given to addNode or new HashRing(), or returns undefined if the ring is empty.
const server = ring.getNode(inputData);
doWorkOn(server);
hashRing.getNodes(input, replicas)
Gets the "replicas" number of nodes that should handle the input, which should be either a string or buffer. The returned array length wiill equal the number of replicas, except if there are fewer nodes available than replicas requested, in which case all nodes are returned.
for (const server of ring.getNodes(input, 2)) {
doWorkOn(server);
}
Related Projects
- libketama -- the original (with native bindings in other languages)
- serialx/hashring -- a library I used in services and where I borrowed implemenation pointers from; Go is much easier for me to read than C :)
- node-hashring -- a prior implementation in JS. It's good but is more complex and makes assumptions about use case; I wanted a very lightweight and generic hashring for use in another libary
Related Skills
node-connect
350.1kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
109.9kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
350.1kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
350.1kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
