zoukankan      html  css  js  c++  java
  • 一致性哈希

    一致性哈希在分布式系统中被很多的使用,比如说memcached就是使用一致性哈希来做的。学习一下这个一致性哈希算法。

    下面这篇博客利用图解的形式,将一致性哈希算法讲述的非常清楚:

    博客:http://blog.codinglabs.org/articles/consistent-hashing.html

    参考代码,下面我列出了java和c#的两个代码实现,可以通过读代码更深刻的去理解一下这个算法。 代码:

    根据上述文章和代码,仿照着写了一个粗略版本的一致性哈希算法。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    public delegate int HashFunction(string val);
     
    public class ConsistentHash<T> where T : class
    {
        //this value used for generate virtual nodes
        private int _replica;
        //Hash fuction used to calculate hash code base on a string
        private HashFunction getHashCode;
        //image this as a big circle which store the node
        private SortedDictionary<int, T> circle = new SortedDictionary<int, T>();
     
        public ConsistentHash(HashFunction hashFunc, ICollection<T> nodes, int replicaNum = 100)
        {
            _replica = replicaNum;
            getHashCode = hashFunc;
            Init(nodes);
        }
     
        public void Add(T node)
        {
            for (int i = 0; i < _replica; i++)
            {
                int hash = getHashCode(node.GetHashCode().ToString() + i);
                circle[hash] = node;
            }
        }
     
        public void Remove(T node)
        {
            for (int i = 0; i < _replica; i++)
            {
                int hash = getHashCode(node.GetHashCode().ToString() + i);
                circle.Remove(hash);
            }
        }
     
        public T GetNode(object key)
        {
            if (key == null)
                return null;
            int hashcode = getHashCode(key.GetHashCode().ToString());
            int firstNode = GetFirst(circle.Keys.ToArray() , hashcode);
            return circle[firstNode];
        }
     
        /// <summary>
        /// use binary search to search the first value in keys array
        /// which bigger than hashcode
        /// if not exist return first key in keys array
        /// </summary>
        /// <param name="keys">key array</param>
        /// <param name="hashcode"></param>
        /// <returns></returns>
        private int GetFirst(int[] keys, int hashcode)
        {
            int beg = 0, end = keys.Length - 1;
            circle.Keys.CopyTo(keys, keys.Length);
            if (hashcode < keys[beg] || hashcode > keys[end])
                return keys[0];
            while (end > beg)
            {
                int mid = (end + beg) / 2;
                if (keys[mid] >= hashcode)
                    end = mid;
                else
                    beg = mid;
            }
            return keys[end];
        }
     
        private void Init(ICollection<T> nodes)
        {
            foreach (T node in nodes)
            {
                Add(node);
            }
        }
    }
    • 没有使用那个默认的Hash code,因为默认的哈希实现可能不够好。最好能够使用自己可以控制的一个好的哈希算法。
    • _replica变量就是每一个结点对应的虚拟节点的个数。虚拟节点是为了解决数据倾斜的问题,也就是说节点分布的不够均匀导致最后分配到每一个节点上的负载不均衡。理论上来说如果实际节点越少,则需要的虚拟节点越多。
    • 使用SortedDictionary是为了查找是能够使用二分查找快速找到一个适合的节点。
  • 相关阅读:
    Spring AOP两种实现方式
    重温SQL——行转列,列转行
    SpringMVC-Spring-Hibernate项目搭建之一-- 搭建maven 项目 & servlet的demo
    Linnx 服务器中mysql 无法正常访问问题
    SpringMVC-Spring-Hibernate项目搭建之三-- freemarker & 静态资源整合
    one2many &&many2many
    SQL学习
    使用Maven导出项目依赖的jar包
    Java Hash Collision之数据生产
    HashMap出现Hash DOS攻击的问题
  • 原文地址:https://www.cnblogs.com/songyanlei/p/3861060.html
Copyright © 2011-2022 走看看