一致性hash算法


public class LoadBalanceManager {

private static TreeMap<Long, Node> nodes; // 虚拟节点到真实节点的映射
private static TreeMap<Long, Node> treeKey; // key到真实节点的映射
private static final int NODE_NUM = 10; // 每个机器节点关联的虚拟节点个数

/**
* 初始化方法,将作为节点的机器List传入作为参数
* @param nodeList
*/
public LoadBalanceManager(List<Node> nodeList) {
nodes = new TreeMap<Long, Node>();
treeKey = new TreeMap<Long, Node>();
for (Node node : nodeList) {
for (int n = 0; n < NODE_NUM; n++) {
// 一个真实机器节点关联NODE_NUM个虚拟节点
nodes.put(hash("SHARD-" + node.getIp() + "-NODE-" + n), node);
}
}
}

/**
* 映射key到真实节点
* @param ip
*/
public void loadBalance(String ip) {
SortedMap<Long, Node> tail = nodes.tailMap(hash(ip)); // 沿环的顺时针找到一个虚拟节点
if (tail.size() == 0) {
// 如果此ip的hash值比任何一个节点的值都大,则取第一个节点
Node first = nodes.firstEntry().getValue();
treeKey.put(hash(ip), first);
System.out.println(ip + "(hash: " + hash(ip) + ")连接到主机->" + first);
return;
}
treeKey.put(hash(ip), tail.get(tail.firstKey()));
System.out.println(ip + "(hash: " + hash(ip) + ")连接到主机->"
+ tail.get(tail.firstKey()));
}

/**
* 增加一个主机
*
* @param node
*/
public void addNode(Node node) {
System.out.println("增加主机" + node + "的变化:");
for (int n = 0; n < NODE_NUM; n++) {
Long key = hash("SHARD-" + node.getIp() + "-NODE-" + n);
addS(key, node);
}
}

/**
* 删除真实节点
*
* @param node
*/
public void deleteNode(Node node) {
if (node == null) {
return;
}
System.out.println("删除主机" + node + "的变化:");
for (int i = 0; i < NODE_NUM; i++) {
// 定位s节点的第i的虚拟节点的位置
Long key = hash("SHARD-" + node.getIp() + "-NODE-" + i);
SortedMap<Long, Node> tail = nodes.tailMap(key);
SortedMap<Long, Node> head = nodes.headMap(key);
Long begin = 0L;
Long end = 0L;

SortedMap<Long, Node> between;
if (head.size() == 0) {
between = treeKey.headMap(nodes.firstKey());
end = tail.firstKey();
tail.remove(end);
// nodes.remove(end);// 从nodes中删除s节点的第i个虚拟节点
} else {
begin = head.lastKey();
end = tail.firstKey();
tail.remove(end);
between = treeKey.subMap(begin, end);// 在s节点的第i个虚拟节点的所有key的集合
}
for (Iterator<Long> it = between.keySet().iterator(); it.hasNext();) {
Long lo = it.next();
treeKey.put(lo, tail.get(tail.firstKey()));
System.out.println("hash(" + lo + ")改变到->"
+ tail.get(tail.firstKey()));
}
}
}

/**
* 添加一个虚拟节点进环形结构,lg为虚拟节点的hash值
*
* @param hashKey
* @param node
*/
private void addS(Long hashKey, Node node) {
SortedMap<Long, Node> tail = nodes.tailMap(hashKey);
SortedMap<Long, Node> head = nodes.headMap(hashKey);
Long begin = 0L;
SortedMap<Long, Node> between;
if (head.size() == 0) {
between = treeKey.headMap(hashKey);
} else {
begin = head.lastKey();
between = treeKey.subMap(begin, hashKey);
}
nodes.put(hashKey, node);
for (Iterator<Long> it = between.keySet().iterator(); it.hasNext();) {
Long lo = it.next();
treeKey.put(lo, nodes.get(hashKey));
System.out.println("hash(" + lo + ")改变到->"
+ tail.get(tail.firstKey()));
}
}

/**
* MurMurHash算法,是非加密HASH算法,性能很高,
* 比传统的CRC32,MD5,SHA-1(这两个算法都是加密HASH算法,复杂度本身就很高,带来的性能上的损害也不可避免)
* 等HASH算法要快很多,而且据说这个算法的碰撞率很低.
*/
private Long hash(String key) {
ByteBuffer buf = ByteBuffer.wrap(key.getBytes());
int seed = 0x1234ABCD;

ByteOrder byteOrder = buf.order();
buf.order(ByteOrder.LITTLE_ENDIAN);

long m = 0xc6a4a7935bd1e995L;
int r = 47;

long h = seed ^ (buf.remaining() * m);

long k;
while (buf.remaining() >= 8) {
k = buf.getLong();

k *= m;
k ^= k >>> r;
k *= m;

h ^= k;
h *= m;
}

if (buf.remaining() > 0) {
ByteBuffer finish = ByteBuffer.allocate(8).order(
ByteOrder.LITTLE_ENDIAN);
finish.put(buf).rewind();
h ^= finish.getLong();
h *= m;
}

h ^= h >>> r;
h *= m;
h ^= h >>> r;

buf.order(byteOrder);
return h;
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值