一致性hash算法
Posted bing
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一致性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}\\t{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 }
运行结果
以上是关于一致性hash算法的主要内容,如果未能解决你的问题,请参考以下文章