SkillAgentSearch skills...

Ketama

Node.js hash ring implementation using libketama-like hashing

Install / Use

/learn @connor4312/Ketama
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

ketama

Actions Status

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

View on GitHub
GitHub Stars4
CategoryDevelopment
Updated2y ago
Forks0

Languages

TypeScript

Security Score

70/100

Audited on Mar 19, 2024

No findings