一致性 hash 算法实现

发布于: 2020 年 07 月 07 日

模拟10个节点,并打印出标准差

package com.hash;

import java.util.*;

import java.util.concurrent.Executors;

import java.util.concurrent.ThreadPoolExecutor;

public class ConsistentHashingWithVirtualNode<T> {

private final HashFunction hashFunction;// hash 函数接口

private final int numberOfReplicas;// 每个机器节点关联的虚拟节点个数

private final SortedMap<Long, T> circle = new TreeMap<Long, T>();// 环形虚拟节点

private static final String IP_PREFIX = "192.168.1.";// 机器节点IP前缀

public ConsistentHashingWithVirtualNode(HashFunction hashFunction, int numberOfReplicas, Collection<T> nodes) {

this.hashFunction = hashFunction;

this.numberOfReplicas = numberOfReplicas;

for (T node : nodes) {

add(node);

}

}

/**

* 增加真实机器节点

*

* @param node

*/

public void add(T node) {

for (int i = 0; i < this.numberOfReplicas; i++) {

circle.put(this.hashFunction.hash(node.toString() + i), node);

}

}

/**

* 删除真实机器节点

*

* @param node

*/

public void remove(T node) {

for (int i = 0; i < this.numberOfReplicas; i++) {

circle.remove(this.hashFunction.hash(node.toString() + i));

}

}

/**

* 取得真实机器节点

*

* @param key

* @return

*/

public T get(String key) {

if (circle.isEmpty()) {

return null;

}

long hash = hashFunction.hash(key);

if (!circle.containsKey(hash)) {

SortedMap<Long, T> tailMap = circle.tailMap(hash);// 沿环的顺时针找到一个虚拟节点

hash = tailMap.isEmpty() ? circle.firstKey() : tailMap.firstKey();

}

return circle.get(hash); // 返回该虚拟节点对应的真实机器节点的信息

}

public static void main(String[] args) {

// 开启多线程测试10w个kv的效果

ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(5);

Map<String, Integer> map = new HashMap<String, Integer>();// 每台真实机器节点上保存的记录条数

List<Node<String>> nodes = new ArrayList<Node<String>>();// 真实机器节点

// 10台真实机器节点集群

for (int i = 1; i <= 10; i++) {

map.put(IP_PREFIX + i, 0);// 每台真实机器节点上保存的记录条数初始为0

Node<String> node = new Node<String>(IP_PREFIX + i, "node" + i);

nodes.add(node);

}

HashFunction hashFunction = new HashFunctionImpl(); // hash函数实例

ConsistentHashingWithVirtualNode<Node<String>> consistentHash = new ConsistentHashingWithVirtualNode<Node<String>>(hashFunction, 100, nodes);// 每台真实机器引入100个虚拟节点

// 10w条kv数据

for (int i = 0; i < 100000; i++) {

// 产生随机一个字符串当做一条记录,可以是其它更复杂的业务对象,比如随机字符串相当于对象的业务唯一标识

String data = UUID.randomUUID().toString() + i;

// 通过记录找到真实机器节点

Node<String> node = consistentHash.get(data);

map.put(node.getIp(), map.get(node.getIp()) + 1);

}

int powSum = 0; // 平方和

for (int i = 1; i <= 10; i++) {

int c = map.get("192.168.1." + i);

powSum += Math.pow((c - 10000), 2);

}

System.out.println("标准差为:" + Math.sqrt(powSum / 10));

}

}

/**

* 虚拟节点

*

* @param <T>

*/

class Node<T> {

private String ip;// IP

private String name;// 名称

public Node(String ip, String name) {

this.ip = ip;

this.name = name;

}

public String getIp() {

return ip;

}

public void setIp(String ip) {

this.ip = ip;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

/**

* 复写toString方法,使用节点IP当做hash的KEY

*/

@Override

public String toString() {

return ip;

}

}

用户头像

方堃

关注

还未添加个人签名 2019.02.11 加入

还未添加个人简介

评论

发布
暂无评论
一致性hash算法实现