using System.Collections.Generic; using System.Linq; using System.Security.Cryptography; using System.Text; namespace Console { class Program { static void Main(string[] args) { var ketAmaNodeLocator = new KetAmaHashingNodeLocator(new List<string> { "192.168.100.124:1442", "192.168.100.124:4555", "192.168.100.125:4444", "192.168.100.124:4477" }); for (var i = 0; i < 100; i++) { System.Console.WriteLine(ketAmaNodeLocator.GetPrimary($"154.244.100.{i}")); } System.Console.ReadLine(); } /// <summary> /// KetAmaHashingNodeLocator /// </summary> public class KetAmaHashingNodeLocator { /// <summary> /// _ketAmaNodes /// </summary> private readonly SortedList<long, string> _ketAmaNodes; /// <summary> /// numReps /// </summary> private readonly int _numReps = 160; /// <summary> /// KetAmaHashingNodeLocator /// </summary> /// <param name="nodes">nodes</param> public KetAmaHashingNodeLocator(IEnumerable<string> nodes/*,int nodeCopies*/) { _ketAmaNodes = new SortedList<long, string>(); //numReps = nodeCopies; //对所有节点,生成nCopies个虚拟结点 foreach (var node in nodes) { //每四个虚拟结点为一组 for (var i = 0; i < _numReps / 4; i++) { //getKeyForNode方法为这组虚拟结点得到惟一名称 var digest = HashAlgorithm.ComputeMd5(node + i); /** Md5是一个16字节长度的数组,将16字节的数组每四个字节一组,分别对应一个虚拟结点,这就是为什么上面把虚拟结点四个划分一组的原因*/ for (var h = 0; h < 4; h++) { var m = HashAlgorithm.Hash(digest, h); _ketAmaNodes[m] = node; } } } } /// <summary> /// GetPrimary /// </summary> /// <param name="k">k</param> /// <returns>string</returns> public string GetPrimary(string k) { var digest = HashAlgorithm.ComputeMd5(k); var rv = GetNodeForKey(HashAlgorithm.Hash(digest, 0)); return rv; } /// <summary> /// GetNodeForKey /// </summary> /// <param name="hash">hash</param> /// <returns>string</returns> private string GetNodeForKey(long hash) { var key = hash; //如果找到这个节点,直接取节点,返回 if (!_ketAmaNodes.ContainsKey(key)) { var tailMap = (from coll in _ketAmaNodes where coll.Key > hash select new { coll.Key }).ToList(); key = !tailMap.Any() ? _ketAmaNodes.FirstOrDefault().Key : tailMap.First().Key; } var rv = _ketAmaNodes[key]; return rv; } } /// <summary> /// HashAlgorithm /// </summary> public class HashAlgorithm { /// <summary> /// Hash /// </summary> /// <param name="digest">digest</param> /// <param name="nTime">nTime</param> /// <returns>long</returns> public static long Hash(byte[] digest, int nTime) { var rv = ((long)(digest[3 + nTime * 4] & 0xFF) << 24) | ((long)(digest[2 + nTime * 4] & 0xFF) << 16) | ((long)(digest[1 + nTime * 4] & 0xFF) << 8) | ((long)digest[0 + nTime * 4] & 0xFF); return rv & 0xffffffffL; /* Truncate to 32-bits */ } /// <summary> /// Get the md5 of the given key. /// </summary> /// <param name="k">key</param> /// <returns>keyBytes</returns> public static byte[] ComputeMd5(string k) { MD5 md5 = new MD5CryptoServiceProvider(); var keyBytes = md5.ComputeHash(Encoding.UTF8.GetBytes(k)); md5.Clear(); //md5.update(keyBytes); //return md5.digest(); return keyBytes; } } } }
转载于:https://www.cnblogs.com/liuxiaoji/p/10309710.html