一致性hash算法[C#]
using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; namespace DevelopmentBasicSkill.Hash { /// <summary> /// hash算法 /// </summary> public class HashAlgorithm { //采用MD5 hash算法先构建16个字节的key public static byte[] getConsistentKeybyMd5(string host) { using (var md5 = new MD5CryptoServiceProvider()) { return md5.ComputeHash(Encoding.UTF8.GetBytes(host)); } } //4个字节一组=32位 public static long getHashCode(byte[] arrConsistentKey, int rowpos) { if (arrConsistentKey == null) { return 0; } if (arrConsistentKey.Length != 16) { return 0; } if (rowpos < 0 || rowpos > 4) { return 0; } long result = ((long)(arrConsistentKey[3 + rowpos * 4] & 0xff) << 24) | ((long)(arrConsistentKey[2 + rowpos * 4] & 0xff) << 16) | ((long)(arrConsistentKey[1 + rowpos * 4] & 0xff) << 8) | ((long)(arrConsistentKey[0 + rowpos * 4] & 0xff) << 0); //32位的环 return result & 0xffffffff; } } }
2. ConsistentHash.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace DevelopmentBasicSkill.Hash { /// <summary> /// 一致性hash算法(包含虚拟节点) /// </summary> public class ConsistentHash { /// <summary> /// 节点,key映射 /// </summary> private SortedList<long, string> nodeMap = new SortedList<long, string>(); /// <summary> /// 虚拟节点重复个数 /// </summary> private int VirtualNodeCount; /// <summary> /// 节点列表 /// </summary> private List<string> NodeList; public ConsistentHash(List<string> nodelist, int virtualNodeCount) { VirtualNodeCount = virtualNodeCount; NodeList = nodelist; init(); } private void init() { foreach (var node in NodeList) { //分四组,md5产生16个字节的key,可构建4个int类型的hashcode //16*8=4*4*8 int runCount = VirtualNodeCount / 4; for (int i = 0; i < runCount; i++) { //16个字节的数据key byte[] hashkey = HashAlgorithm.getConsistentKeybyMd5(node + i); for (int j = 0; j < 4; j++) { nodeMap.Add(HashAlgorithm.getHashCode(hashkey, j), node); } } } } /// <summary> /// 根据关键字取得host服务器 /// </summary> /// <param name="key"></param> /// <returns></returns> public String getHostBykey(string key) { long consistentkey = HashAlgorithm.getHashCode(HashAlgorithm.getConsistentKeybyMd5(key), 0); if (nodeMap.Keys.Contains(consistentkey)) { return nodeMap[consistentkey]; } var result = nodeMap.FirstOrDefault(p => p.Key > consistentkey); if (result.Key > 0) { return result.Value; } return nodeMap.FirstOrDefault().Value; } } }
3.main
using DevelopmentBasicSkill.Hash; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Console_Test { class Program { static void Main(string[] args) { //BasicSkillTest.Test(); //byte[] bts = new byte[] { 1, 2, 3, 4 }; //Console.WriteLine((long)(bts[3] & 0xff)); //long num = (long)(bts[3] & 0xff)<<24; //Console.WriteLine(num); List<string> lstNode = new List<string>(); lstNode.AddRange(new string[] { "192.168.0.1", "192.168.0.2", "192.168.0.3", "192.168.0.4", "192.168.0.5" }); ConsistentHash consisHash = new ConsistentHash(lstNode, 160); for (int i = 0; i < 1000; i++) { string word = Guid.NewGuid().ToString(); Console.WriteLine(i + "\t" + word + ":" + consisHash.getHostBykey(word)); } Console.Read(); } } }