• 一致性hash算法


    参考帖

    https://www.cnblogs.com/mushroom/p/4472369.html

    hash一致性算法hash函数的一种,他的目的在于实现负载均衡,并且每次访问的目标具有一致性,举个例子来说,根据客户端请求ip,经过hash一致性算法,每次计算出来的一致性hash值都是相同的因此每次

    请求的目标主机将是一致的,这种算法广泛使用在负载均衡,数据库水平分表,他的本质在于通过算法的方式计算出key的一致性和唯一性,均衡性

    而一致性hash算法的核心在于增加了虚拟节点来尽可能的达到key值投射到目的主机尽量均衡

    java实现代码:

    http://blog.csdn.net/jerome_s/article/details/52492862

    c#实现代码

      1 public class ConsistencyHash
      2     {
      3 
      4         // 环的所有节点
      5         private SortedList<long, Object> allNodes = null;
      6         // 真实服务器节点
      7         private List<Object> realNodes = new List<object>();
      8         // 设置虚拟节点数目
      9         // 太多会影响性能,太少又会导致负载不均衡,一般说来,经验值是150,
     10         // 当然根据集群规模和负载均衡的精度需求,这个值应该根据具体情况具体对待。
     11         private int VIRTUAL_NODE_COUNT = 150;
     12 
     13         /**
     14          * 初始化一致环
     15          */
     16 
     17         public void init()
     18         {
     19 
     20             // 加入五台真实服务器
     21             realNodes.Add("192.168.0.0-服务器0");
     22             realNodes.Add("192.168.0.1-服务器1");
     23             realNodes.Add("192.168.0.2-服务器2");
     24             realNodes.Add("192.168.0.3-服务器3");
     25             realNodes.Add("192.168.0.4-服务器4");
     26 
     27             // 构造每台真实服务器的虚拟节点
     28             allNodes = new SortedList<long, object>();
     29             for (int i = 0; i < realNodes.Count(); i++)
     30             {
     31                 Object nodeInfo = realNodes[i];
     32                 for (int j = 0; j < VIRTUAL_NODE_COUNT; j++)
     33                 {
     34                     var cpm = "NODE-" + i + "-VIRTUAL-" + j;
     35                     var md5 = computeMd5(cpm);
     36                     var hashVal = hash(md5, 0);
     37                     allNodes.Add(hashVal, nodeInfo);
     38 
     39                     Console.WriteLine(string.Format("{0}	{1}", cpm,hashVal));
     40                 }
     41             }
     42         }
     43 
     44         /**
     45          * 计算MD5值
     46          */
     47 
     48         public byte[] computeMd5(String k)
     49         {
     50 
     51             MD5 md5 = new MD5CryptoServiceProvider();
     52 
     53             byte[] keyBytes = md5.ComputeHash(Encoding.UTF8.GetBytes(k));
     54             md5.Clear();
     55             //md5.update(keyBytes);
     56             //return md5.digest();
     57             return keyBytes;
     58         }
     59 
     60         /**
     61          * 根据2^32把节点分布到环上面
     62          *
     63          * @param digest
     64          * @param nTime
     65          * @return
     66          */
     67 
     68         public long hash(byte[] digest, int nTime)
     69         {
     70             long rv = ((long) (digest[3 + nTime*4] & 0xFF) << 24)
     71                       | ((long) (digest[2 + nTime*4] & 0xFF) << 16)
     72                       | ((long) (digest[1 + nTime*4] & 0xFF) << 8)
     73                       | (digest[0 + nTime*4] & 0xFF);
     74 
     75             return rv & 0xffffffffL; /* Truncate to 32-bits */
     76         }
     77 
     78 
     79         /**
     80          * 根据key的hash值取得服务器节点信息
     81          *
     82          * @param hash
     83          * @return
     84          */
     85 
     86         public Object getNodeInfo(long hash)
     87         {
     88 
     89             string rv;
     90             long key = hash;
     91             //如果找到这个节点,直接取节点,返回   
     92             if (!allNodes.ContainsKey(key))
     93             {
     94                 //得到大于当前key的那个子Map,然后从中取出第一个key,就是大于且离它最近的那个key 说明详见: http://www.javaeye.com/topic/684087
     95                 var tailMap = from coll in allNodes
     96                     where coll.Key > hash
     97                     select new {coll.Key};
     98                 if (tailMap == null || tailMap.Count() == 0)
     99                     key = allNodes.FirstOrDefault().Key;
    100                 else
    101                     key = tailMap.FirstOrDefault().Key;
    102             }
    103             return allNodes[key];
    104         }
    105 
    106     }

    示例使用代码

     1 static void Main(string[] args)
     2         {
     3             ConsistencyHash consistencyHash = new ConsistencyHash();
     4             consistencyHash.init();
     5 
     6             int _0 = 0;
     7             int _1 = 0;
     8             int _2 = 0;
     9             int _3 = 0;
    10             int _4 = 0;
    11 
    12             Random ran = new Random();
    13             for (int i = 0; i < 50000; i++)
    14             {
    15                 // 随便取一个数的md5
    16                 byte[] ranNum = consistencyHash.computeMd5(i.ToString());
    17 
    18                 // 分配到随即的hash环上面
    19                 long key = consistencyHash.hash(ranNum, 2);
    20                 // long key = consistencyHash.hash(ranNum, ran.nextInt(consistencyHash.VIRTUAL_NODE_COUNT));
    21 
    22                 // 获取他所属服务器的信息
    23                 // System.out.println(consistencyHash.getNodeInfo(key));
    24                 if (consistencyHash.getNodeInfo(key).Equals("192.168.0.0-服务器0"))
    25                 {
    26                     _0++;
    27                 }
    28                 else if (consistencyHash.getNodeInfo(key).Equals("192.168.0.1-服务器1"))
    29                 {
    30                     _1++;
    31                 }
    32                 else if (consistencyHash.getNodeInfo(key).Equals("192.168.0.2-服务器2"))
    33                 {
    34                     _2++;
    35                 }
    36                 else if (consistencyHash.getNodeInfo(key).Equals("192.168.0.3-服务器3"))
    37                 {
    38                     _3++;
    39                 }
    40                 else if (consistencyHash.getNodeInfo(key).Equals("192.168.0.4-服务器4"))
    41                 {
    42                     _4++;
    43                 }
    44                 else
    45                 {
    46                     Console.WriteLine("error");
    47                 }
    48             }
    49 
    50             // 输出每台服务器负载情况
    51             Console.WriteLine("_0 = " + _0);
    52             Console.WriteLine("_1 = " + _1);
    53             Console.WriteLine("_2 = " + _2);
    54             Console.WriteLine("_3 = " + _3);
    55             Console.WriteLine("_4 = " + _4);
    56 
    57             Console.Read();
    58 
    59         }

     运行结果

  • 相关阅读:
    day02-数据库操作
    day01-MySQL介绍
    3-socketserver
    1-多线程与多进程
    keyword模块
    math模块
    查看进程pid与ppid
    开启进程的两种方式
    进程理论
    进程
  • 原文地址:https://www.cnblogs.com/rjjs/p/8024609.html
Copyright © 2020-2023  润新知