Skip to content
This repository has been archived by the owner on Feb 10, 2022. It is now read-only.

Commit

Permalink
Added the capability to select virtual nodes per shard.
Browse files Browse the repository at this point in the history
This feature enable to do a progressive miss on shard added, so you could
modify the amount of new vnodes progressively getting a better distribution
of misses on shard added
  • Loading branch information
Gabriel Eisbruch committed Sep 18, 2012
1 parent ecfbcdc commit 0447337
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 7 deletions.
35 changes: 28 additions & 7 deletions lib/hashring.js
Expand Up @@ -23,15 +23,27 @@ var createHash = require('crypto').createHash

function HashRing (args, algorithm, options) {
var nodes = []
, weights = {};
, weights = {}
, vnodes = {};

switch (Object.prototype.toString.call(args)){
case '[object String]':
nodes.push(args);
break;
case '[object Object]':
weights = args;
nodes = Object.keys(args);
for(var i in args){
if(typeof args[i] === "number"){
weights[i] = args[i];
}else{
if(args[i].weigth != undefined){
weights[i] = args[i].weigth;
}
if(args[i].vnodes != undefined){
vnodes[i] = args[i].vnodes;
}
}
}
break;
case '[object Undefined]':
break;
Expand All @@ -49,6 +61,7 @@ function HashRing (args, algorithm, options) {

this.nodes = nodes || [];
this.weights = weights;
this.vnodes = vnodes;
this.algorithm = algorithm || 'crc32';

// overwrite the hashKey method if crc32 is chosen
Expand Down Expand Up @@ -105,11 +118,10 @@ HashRing.prototype.generateRing = function generateRing () {

// The factor is based on the weight, the more weight the more space a item
// will get in our hash ring
factor = Math.floor((this.options.vnode_count * len * weight) / totalweight);

var vnodes_count = this.vnodes[node] || this.options.vnode_count
factor = Math.floor((vnodes_count * len * weight) / totalweight);
for (j = 0; j < factor; j++) {
tmp = this.hashKey(node + '-' + j);

for (k = 0; k < 3; k++) {
key = this.hashValue(tmp, function hash (x) {
return x + k * 4;
Expand All @@ -120,7 +132,6 @@ HashRing.prototype.generateRing = function generateRing () {
}
}
}

// Sort the keys, nummeric !important. I forgot it at first and took me
// 2 hours to debug \o/
this.sortedKeys.sort(function sort (a, b) {
Expand Down Expand Up @@ -207,7 +218,7 @@ HashRing.prototype.replaceServer = function replaceServer (oldServer, newServer)
* @api public
*/

HashRing.prototype.addServer = function addServer (server, weights) {
HashRing.prototype.addServer = function addServer (server, weights, vnodes) {
if (this.nodes.indexOf(server) !== -1) return; // prevents duplicates

// add weights
Expand All @@ -217,6 +228,12 @@ HashRing.prototype.addServer = function addServer (server, weights) {
}
}

// add vnodes
if (vnodes) {
for(var key in vnodes) {
this.vnodes[key] = vnodes[key];
}
}
if (!Array.isArray(server)) {
server = [server];
}
Expand Down Expand Up @@ -247,6 +264,10 @@ HashRing.prototype.removeServer = function removeServer (server) {
delete this.weights[server];
}

if (this.vnodes[server]) {
delete this.weights[server];
}

// clear all old caches and regenerate
this.ring = {};
this.cache = {};
Expand Down
18 changes: 18 additions & 0 deletions tests/hashring.test.js
Expand Up @@ -38,7 +38,25 @@ module.exports = {
ring.sortedKeys.length.should.be.above(1);
Object.keys(ring.weights).should.have.length(3);
}
, 'Constructing with a object with pernode vnodes': function(){
var ring = new Hashring({
'192.168.0.102:11212': {"vnodes":40}
, '192.168.0.103:11212': {"vnodes":50}
, '192.168.0.104:11212': {"vnodes":5}
});
ring.nodes.should.have.length(3);
ring.sortedKeys.length.should.be.equal((40+50+5)*3)

ring = new Hashring({
'192.168.0.102:11212': {"vnodes":4}
, '192.168.0.103:11212': {"vnodes":3}
, '192.168.0.104:11212': {"vnodes":5}
});
ring.nodes.should.have.length(3);
ring.sortedKeys.length.should.be.equal((4+3+5)*3)


}
, 'Constructing with a different algorithm': function () {
var ring = new Hashring('192.168.0.102:11212', 'md5');

Expand Down

0 comments on commit 0447337

Please sign in to comment.