zoukankan      html  css  js  c++  java
  • 一致性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         }

     运行结果

  • 相关阅读:
    容器跨主机网络通信学习笔记(以Flannel为例)
    Kubernetes控制器Job和CronJob
    记一次使用Flannel插件排错历程
    Kubernetes控制器Deployment
    Kubernetes如何通过StatefulSet支持有状态应用?
    react18 来了,我 get 到...
    gojs 实用高级用法
    vuecli3 vue2 保留 webpack 支持 vite 成功实践
    calibre 报错 This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem. 解决
    unable to recognize "*.yaml": no matches for kind "RoleBinding" in version "rbac.authorization.k8s.io/v1beta1"
  • 原文地址:https://www.cnblogs.com/rjjs/p/8024609.html
Copyright © 2011-2022 走看看