Consistent Hashing最大限度地抑制了hash键的重新分布。另外要取得比较好的负载均衡的效果,往往在服务器数量比较少的时候需要增加虚拟节点来保证服务器能均匀的分布在圆环上。因为使用一般的hash方法,服务器的映射地点的分布非常不均匀。使用虚拟节点的思想,为每个物理节点(服务器)在圆上分配100~200个点。这样就能抑制分布不均匀,最大限度地减小服务器增减时的缓存重新分布。用户数据映射在虚拟节点上,就表示用户数据真正存储位置是在该虚拟节点代表的实际物理服务器上。

public class KetamaNodeLocator
{
//原文中的JAVA类TreeMap实现了Comparator方法,这里我图省事,直接用了net下的SortedList,其中Comparer接口方法)
private SortedList<long, string> ketamaNodes = new SortedList<long, string>();
private HashAlgorithm hashAlg;
private int numReps = 160; //此处参数与JAVA版中有区别,因为使用的静态方法,所以不再传递HashAlgorithm alg参数
public KetamaNodeLocator(List<string> nodes, int nodeCopies)
{
ketamaNodes = new SortedList<long, string>(); numReps = nodeCopies;
//对所有节点,生成nCopies个虚拟结点
foreach (string node in nodes)
{
//每四个虚拟结点为一组
for (int i = 0; i < numReps / 4; i++)
{
//getKeyForNode方法为这组虚拟结点得到惟一名称
byte[] digest = HashAlgorithm.computeMd5(node + i);
/** Md5是一个16字节长度的数组,将16字节的数组每四个字节一组,分别对应一个虚拟结点,这就是为什么上面把虚拟结点四个划分一组的原因*/
for (int h = 0; h < 4; h++)
{
long m = HashAlgorithm.hash(digest, h);
ketamaNodes[m] = node;
}
}
}
} public string GetPrimary(string k)
{
byte[] digest = HashAlgorithm.computeMd5(k);
string rv = GetNodeForKey(HashAlgorithm.hash(digest, 0));
return rv;
} string GetNodeForKey(long hash)
{
string rv;
long key = hash;
//如果找到这个节点,直接取节点,返回
if (!ketamaNodes.ContainsKey(key))
{
//得到大于当前key的那个子Map,然后从中取出第一个key,就是大于且离它最近的那个key 说明详见: http://www.javaeye.com/topic/684087
var tailMap = from coll in ketamaNodes
where coll.Key > hash
select new { coll.Key };
if (tailMap == null || tailMap.Count() == 0)
key = ketamaNodes.FirstOrDefault().Key;
else
key = tailMap.FirstOrDefault().Key;
}
rv = ketamaNodes[key];
return rv;
}
}

  总结一致性哈希(Consistent Hashing)  http://www.iteye.com/topic/611976

Ketama一致性Hash算法学习(含Java代码) http://www.iteye.com/topic/684087

最新文章

  1. MySQL数据类型 int(M) 表示什么意思?详解mysql int类型的长度值问题
  2. 关于vue.js中class与style绑定的学习
  3. 基于ZooKeeper的Dubbo注册中心
  4. yum缓存配置
  5. C# 时间现实问题(12小时制与24小时制)
  6. TFS代码签入指导
  7. go语言使用protobuf
  8. linux bash_profile和.bashrc区别
  9. [itint5]合并K个有序链表
  10. 01线性表顺序存储_List--(线性表)
  11. sqlite 数据库打开失败
  12. Day9 网络编程
  13. CMake高速入门
  14. C语言之可重入函数 &amp;&amp; 不可重入函数
  15. [SDOI2016]储能表
  16. 【BZOJ 4031】: [HEOI2015]小Z的房间
  17. 介绍Dynamics 365 Performance Center
  18. Jeesite 代码生成
  19. pycharm 注册码/License server 2017年最新
  20. 九、使用多线程——NSThread,GCD和NSOperation

热门文章

  1. A1084
  2. windows从0开始学golang--0--安装golang+git+自己写包
  3. 转载: 国内的go get无法连接问题的解决
  4. Playing audio from Node.js using Edge.js
  5. WPF Expander获得ToggleButton
  6. void与NULL详解
  7. [算法]用java实现堆操作
  8. SpringBoot日记——Thymeleaf模板引擎篇
  9. 【日常训练】Help Far Away Kingdom(Codeforces 99A)
  10. gradle springboot 项目运行的三种方式