hash算法实现代码如下:
继承自c#的HashAlgorithm类

public class FNV1a : HashAlgorithm { private const uint Prime = 16777619; private const uint Offset = 2166136261; protected uint CurrentHashValue; public FNV1a() { this.HashSizeValue = 32; this.Initialize(); } public override void Initialize() { this.CurrentHashValue = Offset; } protected override void HashCore(byte[] array, int ibStart, int cbSize) { int end = ibStart + cbSize; for (int i = ibStart; i < end; i++) this.CurrentHashValue = (this.CurrentHashValue ^ array[i]) * FNV1a.Prime; } protected override byte[] HashFinal() { return BitConverter.GetBytes(this.CurrentHashValue); } }
实现修改后的算法

public class ModifiedFNV : FNV1a { protected override byte[] HashFinal() { this.CurrentHashValue += this.CurrentHashValue << 13; this.CurrentHashValue ^= this.CurrentHashValue >> 7; this.CurrentHashValue += this.CurrentHashValue << 3; this.CurrentHashValue ^= this.CurrentHashValue >> 17; this.CurrentHashValue += this.CurrentHashValue << 5; return base.HashFinal(); // return base.HashFinal } }
节点均衡类

public sealed class DefaultNodeLocator { private List<string> servers = new List<string>(); public void Initialize(List<string> nodes) { this.servers = nodes; } public string Locate(string key) { uint itemKeyHash = BitConverter.ToUInt32(new ModifiedFNV().ComputeHash(Encoding.Unicode.GetBytes(key)), 0); return this.servers[Convert.ToInt16(itemKeyHash % servers.Count)]; } private static List<uint> GenerateKeys(string node, int numberOfKeys) { const int KeyLength = 4; const int PartCount = 1; List<uint> k = new List<uint>(PartCount * numberOfKeys); for (int i = 0; i < numberOfKeys; i++) { byte[] data = new ModifiedFNV().ComputeHash(Encoding.ASCII.GetBytes(String.Concat(node, "-", i))); for (int h = 0; h < PartCount; h++) k.Add(BitConverter.ToUInt32(data, h * KeyLength)); } return k; } }
实现demo
class Program { static void Main(string[] args) { List<string> servers = new List<string>(new string[] { "A", "B", "C", "D" }); Dictionary<string, List<string>> cache = new Dictionary<string, List<string>>(); DefaultNodeLocator locator = new DefaultNodeLocator(); locator.Initialize(servers); Init(locator, servers, cache); Console.WriteLine("实例的个数{0}", cache.Count); Info(cache); Console.WriteLine("测试某一个实例发生了问题"); string s = servers[0]; var removed = cache[s]; cache.Remove(s); servers.Remove(s); Test(locator, cache); Console.WriteLine("测试需要增加一个实例"); servers = new List<string>(new string[] { "A", "B", "C", "D", "E" }); locator = new DefaultNodeLocator(); locator.Initialize(servers); cache.Add(s, removed); Test(locator, cache); Console.WriteLine("经过一段时间后的节点分配情况"); cache = new Dictionary<string, List<string>>(); Init(locator, servers, cache); Info(cache); Console.ReadLine(); } static void Test(DefaultNodeLocator locator, Dictionary<string, List<string>> cache) { Console.Write("没有命中的节点:"); int failed = 0; for (int i = 0; i < 100; i++) { string key = i.ToString(); string value = i.ToString(); string server = locator.Locate(key); if (!cache.ContainsKey(server) || !cache[server].Contains(key)) { failed++; Console.Write(string.Format("{0} -> {1}", key, server) + ","); } } Console.WriteLine(); Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("命中率为 {0} %", 100 - failed); Console.ForegroundColor = ConsoleColor.Gray; } static void Init(DefaultNodeLocator locator, List<string> servers, Dictionary<string, List<string>> cache) { for (int i = 0; i < 100; i++) { string key = i.ToString(); string value = i.ToString(); string server = locator.Locate(key); if (!cache.ContainsKey(server)) cache.Add(server, new List<string>()); cache[server].Add(value); } } static void Info(Dictionary<string, List<string>> cache) { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("每一个实例缓存分布情况如下:"); Console.ForegroundColor = ConsoleColor.Gray; foreach (var server in cache) { StringBuilder sb = new StringBuilder(); var values = server.Value; sb.Append(string.Format("{0} ({1}values) : ", server.Key, values.Count)); foreach (var value in values) { sb.Append(value + ","); } Console.WriteLine(sb.ToString()); } } }