写点什么

一期二班 - 吴水金 - 第五课作业

用户头像
吴水金
关注
发布于: 2020 年 11 月 04 日

一致性 hash 算法 C#实现

代码:

using System;using System.Collections.Generic;using System.Linq;using System.Security.Cryptography;using System.Text;
namespace Hash{ class Program { static void Main(string[] args) { ConsistencyHash consistencyHash = new ConsistencyHash(); consistencyHash.init();
int _0 = 0; int _1 = 0; int _2 = 0; int _3 = 0; int _4 = 0; int _5 = 0; int _6 = 0; int _7 = 0; int _8 = 0; int _9 = 0;
Random ran = new Random(); long startTicks = DateTime.Now.Ticks;
for (int i = 0; i < 1000000; i++) { // 随便取一个数的md5 byte[] ranNum = consistencyHash.computeMd5(i.ToString());
// 分配到随即的hash环上面 long key = consistencyHash.hash(ranNum, 2);
if (consistencyHash.getNodeInfo(key).Equals("192.168.0.0-服务器0")) { _0++; } else if (consistencyHash.getNodeInfo(key).Equals("192.168.0.1-服务器1")) { _1++; } else if (consistencyHash.getNodeInfo(key).Equals("192.168.0.2-服务器2")) { _2++; } else if (consistencyHash.getNodeInfo(key).Equals("192.168.0.3-服务器3")) { _3++; } else if (consistencyHash.getNodeInfo(key).Equals("192.168.0.4-服务器4")) { _4++; } else if (consistencyHash.getNodeInfo(key).Equals("192.168.0.5-服务器5")) { _5++; } else if (consistencyHash.getNodeInfo(key).Equals("192.168.0.6-服务器6")) { _6++; } else if (consistencyHash.getNodeInfo(key).Equals("192.168.0.7-服务器7")) { _7++; } else if (consistencyHash.getNodeInfo(key).Equals("192.168.0.8-服务器8")) { _8++; } else if (consistencyHash.getNodeInfo(key).Equals("192.168.0.9-服务器9")) { _9++; } else { Console.WriteLine("error"); } }
// 输出每台服务器负载情况 Console.WriteLine("server_0 = " + _0); Console.WriteLine("server_1 = " + _1); Console.WriteLine("server_2 = " + _2); Console.WriteLine("server_3 = " + _3); Console.WriteLine("server_4 = " + _4); Console.WriteLine("server_5 = " + _5); Console.WriteLine("server_6 = " + _6); Console.WriteLine("server_7 = " + _7); Console.WriteLine("server_8 = " + _8); Console.WriteLine("server_9 = " + _9);
Console.WriteLine("时长:{0}ms", DateTime.Now.Ticks - startTicks);
Console.Read(); } }
public class ConsistencyHash { // 环的所有节点 private SortedList<long, object> allNodes = null; // 真实服务器节点 private List<Object> realNodes = new List<object>(); // 设置虚拟节点数目 // 太多会影响性能,太少又会导致负载不均衡,一般说来,经验值是150, // 当然根据集群规模和负载均衡的精度需求,这个值应该根据具体情况具体对待。 private int VIRTUAL_NODE_COUNT = 150;
public void init() { // 加入10台真实服务器 realNodes.Add("192.168.0.0-服务器0"); realNodes.Add("192.168.0.1-服务器1"); realNodes.Add("192.168.0.2-服务器2"); realNodes.Add("192.168.0.3-服务器3"); realNodes.Add("192.168.0.4-服务器4"); realNodes.Add("192.168.0.5-服务器5"); realNodes.Add("192.168.0.6-服务器6"); realNodes.Add("192.168.0.7-服务器7"); realNodes.Add("192.168.0.8-服务器8"); realNodes.Add("192.168.0.9-服务器9");
// 构造每台真实服务器的虚拟节点 allNodes = new SortedList<long, object>(); for(int i = 0; i < realNodes.Count; i++) { object node = realNodes[i]; for(int j = 0; j < VIRTUAL_NODE_COUNT; j++) { var cpm = "NODE-" + i + "-VIRTUAL-" + j; var md5 = computeMd5(cpm); var hashVal = hash(md5, 0);//使用MD5值计算hash值 allNodes.Add(hashVal, node); //Console.WriteLine(string.Format("{0}\t{1}", cpm, hashVal)); } }
} /** * 计算MD5值 */ public byte[] computeMd5(String k) { MD5 md5 = new MD5CryptoServiceProvider(); byte[] keyBytes = md5.ComputeHash(Encoding.UTF8.GetBytes(k)); md5.Clear(); //md5.update(keyBytes); //return md5.digest(); return keyBytes; }
/** * 根据2^32把节点分布到环上面 * * @param digest * @param nTime * @return */ public long hash(byte[] digest, int nTime) { long rv = ((long)(digest[3 + nTime * 4] & 0xFF) << 24) | ((long)(digest[2 + nTime * 4] & 0xFF) << 16) | ((long)(digest[1 + nTime * 4] & 0xFF) << 8) | (digest[0 + nTime * 4] & 0xFF);

return rv & 0xffffffffL; /* Truncate to 32-bits */ }
/** * 根据key的hash值取得服务器节点信息 * * @param hash * @return */ public Object getNodeInfo(long hash) { string rv; long key = hash; //如果找到这个节点,直接取节点,返回 if (!allNodes.ContainsKey(key)) { //得到大于当前key的那个子Map,然后从中取出第一个key,就是大于且离它最近的那个key var tailMap = from coll in allNodes where coll.Key > hash select new {coll.Key}; if (tailMap == null || tailMap.Count() == 0) key = allNodes.FirstOrDefault().Key; else key = tailMap.FirstOrDefault().Key; } return allNodes[key]; }}}
复制代码


10 台服务器 100 万 KV 数据的节点分布情况:

server_0 = 100547

server_1 = 105269

server_2 = 105279

server_3 = 107685

server_4 = 88297

server_5 = 93284

server_6 = 104584

server_7 = 110483

server_8 = 101650

server_9 = 82922

耗时:2333570000 毫秒


发布于: 2020 年 11 月 04 日阅读数: 29
用户头像

吴水金

关注

初级架构师 2019.12.01 加入

热情开朗,乐于分享。

评论

发布
暂无评论
一期二班 - 吴水金 - 第五课作业