Consist Hash
A concsit hash sample using Cpp language.
Just check out in any environment that has C++ compiler and run it!
#include <iostream>
#include <string>
#include <math.h>
#include <map>
#include <fstream>
#include <random>
#include <ctime>
#define MAX_HASH_NODE_NUM 100
#define DEBUG_MODE 0
using namespace std;
struct serverNode
{
int type; //virtual:0 real:1
string toIP; //for virt node
string IP; //for real node
int visit_num;
};
map<int,serverNode> HashNodes;
int getHash(unsigned char *str)
{//fnv1_32_hash
int p = 16777619;
int hash = (int) 2166136261L;
int c;
while(c = *str++)
{
hash = (hash ^ c) * p;
}
hash += hash << 13;
hash ^= hash >> 7;
hash += hash << 3;
hash ^= hash >> 17;
hash += hash << 5;
if (hash < 0)
{
hash = abs(hash);
}
return hash;
}
string num_to_string(int num)
{
int x = num;
int len = 0;
string __res;
while(x!=0)
{
len ++;
x = x / 10;
}
x = num;
for (int i = len; i > 0; --i)
{
char c = (x / pow(10,i - 1) + '0');
__res += c;
x = x % (int)pow(10,i - 1);
}
return __res;
}
void add_server_node(serverNode& node)
{
int key;
if(node.type == 1)
{
key = getHash((unsigned char*)node.IP.c_str());
pair<int,serverNode> temp;
temp.first = key;
temp.second = node;
HashNodes.insert(temp);
}
else if (node.type == 0)
{
//key = getHash((unsigned char*)node.IP.c_str());
int randnum = rand() % 1000;
string tempstr = node.toIP + num_to_string(randnum);
key = getHash( (unsigned char*) tempstr.c_str() );
pair<int,serverNode> temp;
temp.first = key;
temp.second = node;
HashNodes.insert(temp);
}
}
void init_server_node(serverNode& node, int servertype)
{
if (servertype != 0 && servertype != 1)
{
printf("Server Type Error!\n");
exit(1);
}
node.type = servertype;
node.visit_num = 0;
}
void show_all_servers()
{
map<int,serverNode>::iterator iter;
for (iter = HashNodes.begin(); iter != HashNodes.end(); iter++)
{
// cout << iter->first << " " << iter->second.IP << endl;
if (iter->second.type == 1)
{
cout << "Real: key:" << iter->first << " IP:" << iter->second.IP << endl;
}
else
{
cout << "Virtual: key:" << iter->first << " toIP:" << iter->second.toIP << endl;
}
}
}
void show_all_real_visit()
{
int sum = 0;
map<int,serverNode>::iterator iter;
for (iter = HashNodes.begin(); iter != HashNodes.end(); iter++)
{
if (iter->second.type == 1)
{
cout << " IP:" << iter->second.IP << " visited time: " << iter->second.visit_num << endl;
sum += iter->second.visit_num;
}
}
cout << "total visited time: " << sum << endl;
double sum2 = sum;
for (iter = HashNodes.begin(); iter != HashNodes.end(); iter++)
{
if (iter->second.type == 1)
{
cout << " IP:" << iter->second.IP << " visited rate: " << (iter->second.visit_num/sum2) * 100.0 << "%" << endl;
}
}
}
int main(int argc, char const *argv[])
{
srand(time(0));
string IP_address_raw = "192.168.0.";
// add real nodes
for (int i = 1; i < 11; i++) // from "192.168.0.1" to "192.168.0.10"
{
string realIP = IP_address_raw + num_to_string(i);
serverNode temp;
temp.IP = realIP;
init_server_node(temp, 1);
add_server_node(temp);
}
// add virual nodes each 9 virtual nodes refer to 1 real node
for (int i = 0; i < 90; i++)
{
string virtIP = IP_address_raw + num_to_string(i/9 + 1);
serverNode temp;
temp.toIP = virtIP;
init_server_node(temp,0);
add_server_node(temp);
}
// show_all_servers();
// generate keys to visit
for (int i = 0; i < 1000000; i++)
{
//random set key
int key = rand() % 2147483647;
int key_hash = getHash((unsigned char*) num_to_string(key).c_str());
map<int,serverNode>::iterator iter;
iter = HashNodes.lower_bound(key_hash); //Find node to visit
if(iter != HashNodes.end())
{
if (iter->second.type == 1) // for real node
{
iter->second.visit_num++;
}
else // for virtual node, find the real node it goes to.
{
map<int,serverNode>::iterator iter2;
for (iter2 = HashNodes.begin(); iter2!= HashNodes.end(); iter2++)
{
if(iter2->second.type == 1)
{
if (iter2->second.IP == iter->second.toIP)
{
iter2->second.visit_num++;
}
}
}
}
}
else //The max key goes to the first node
{
iter = HashNodes.begin();
if (iter->second.type == 1) // for real node
{
iter->second.visit_num++;
}
else
{
map<int,serverNode>::iterator iter2;
for (iter2 = HashNodes.begin(); iter2!= HashNodes.end(); iter2++)
{
if(iter2->second.type == 1)
{
if (iter2->second.IP == iter->second.toIP)
{
iter2->second.visit_num++;
}
}
}
}
}
}
show_all_real_visit();
return 0;
}