一致性hash的c++简单实现

来源:互联网 发布:网络教学综合平台 编辑:程序博客网 时间:2024/05/21 06:53

很晚了,一致性hash的理论不再多说,直接上我写的c++代码

代码功能:
1,初始化一些实际的server节点,每个server节点生成一堆虚拟节点
2,将所有的虚拟节点根据它的名字生成的hash key散布到一个环内
3,对新插入环内的元素(随机生成),计算它的hash key,然后在环中寻找大于等于它的虚拟节点,根据虚拟节点即可找到物理节点。随机生成很多歌元素,查看散布到各个节点的元素数量是否均衡。

代码一些特点:
对于server节点,只需要存储它的虚拟节点hash值以及与实际server名字的对应。对于新插入的元素,为了快速找到它所存放的位置(即大于等于它的hash值的虚拟节点),应该采用二分查找。 故而,虚拟节点使用map结构存储,底层是红黑树的实现,类似于二分,同时支持高效的插入删除。 当新的虚拟节点插入到环内,只需要移动很少量的元素到它上面。

还有chord算法要好好看看,还没有看。

#include<iostream>#include <sstream>#include <string>#include <vector>#include <list>#include <stack>#include <queue>#include <algorithm>#include <map>#include <set>#include <unordered_map>#include <unordered_set>#include <iomanip>#include <random>#include <cstring>#include <cmath>#include <cstdlib>#include <cstdio>using namespace std;typedef unsigned long Key;template <class T>struct NodeHasher{    template <class T>    Key operator() (const T& t){        return 0;    }    template <>    Key operator()<string> (const string& t){        return hash2((unsigned char*)t.c_str());    }public:    //not a good hash function    static unsigned long hash(unsigned char *str)    {        unsigned long hash = 5381;        int c;        while (c = *str++)            hash = ((hash << 5) + hash) + c; /* hash * 33 + c */        return hash;    }    static unsigned long hash2(unsigned char *str)    {        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;    }};template <class T>class ConsistentHash{public:    ConsistentHash(int numberOfReplica = 150, bool isTest = false, int server=5): numOfReplicas(numberOfReplica){        if (isTest)        {            for (int c = 0; c < server; ++c)            {                addServer(to_string(c));            }        }    }public:    void addServer(T node){        cout << "add real server:" << node << endl;        for (int i = 0; i < numOfReplicas; ++i)        {            Key k = NodeHasher<T>()(node + std::to_string(i));            if (i < 2)                cout << "   virtual server: " << k << endl;            else if (i == 2)                cout << "   ... " <<numOfReplicas<< endl;            circles.insert({ k, node });        }    }    void removeServer(T node){        cout << "remove real server:" << node << endl;        for (int i = 0; i < numOfReplicas; ++i)        {            Key k = NodeHasher<T>()(node+std::to_string(i));            auto it = circles.find(k);            if (it != circles.end()) circles.erase(it);        }    }public:    T get(Key k){        auto it = circles.find(k);        if (it != circles.end()) return it->second;        it = circles.lower_bound(k);        return (it == circles.end()) ? circles.begin()->second : it->second;    }public:    static void testIt(){        int number = 100000;        int server = 10;        int virutal_server = 150;        ConsistentHash chash(virutal_server, true, server);        struct {            void operator()(int number, ConsistentHash& chash) {                map<T, int> countNumMap;                std::random_device seed;                std::mt19937 gen(seed());                std::uniform_int_distribution<int> dist(0, LONG_MAX);                for (int i = 0; i < number; ++i)                {                    Key k = dist(gen);                    T node = chash.get(k);                    countNumMap[node]++;                }                cout << "server numOfElems:" << endl;                for (auto it : countNumMap){                    cout << it.first << " " << it.second << " " << std::setprecision(2) << it.second*1.0 / number << endl;                }            }        }show;        for (int i = 0; i < server; ++i)        {            show(number, chash);            chash.removeServer(std::to_string(i));        }    }private:    int numOfReplicas;    map<Key, T> circles;};int main(){    ConsistentHash<string>::testIt();    return 0;}
0 0
原创粉丝点击