Java实现一致性hash算法

    做个记录 防止老了忘掉    

   1)实现代码:

        思路:

           1)使用md5 加密节点名 得到byte[]  

           2)将byte[] 转换为整数  得到节点位置

           3)使用TreeMap 记录 所有的  节点名  和节点对应的位置(一个节点对应多个虚拟位置)节点位置为key 节点名为value

                     格式为:

        // 节点键值集合
	private TreeMap<Integer, String> nodes = new TreeMap<Integer, String>();

           4)使用 HashMap 记录 单个节点 和 其对应的所有虚假节点 (方便移除节点等其他操作)

            格式为:

       // 记录每个node 对应的 虚拟节点集合
	private Map<String, List<Integer>> nodeposition = new HashMap<String, List<Integer>>();

  2)完整代码:    

package yuan;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

/**
 * 一致性hash 算法
 * 
 * @author Yuan
 * 
 */
public class ConsistentHash {

	// 节点键值集合
	private TreeMap<Integer, String> nodes = new TreeMap<Integer, String>();

	// 记录每个node 对应的 虚拟节点集合
	private Map<String, List<Integer>> nodeposition = new HashMap<String, List<Integer>>();

	// 一个节点的虚拟节点数
	private int nodeMul = 64;

	// public
	public void addNode(String nodeName) {
		// 无虚拟节点写法
		// Integer position = MD5Utils.GetMD5CodeToInt(nodeName);
		// nodes.put(position, nodeName);
		// positions = nodes.keySet();

		// 引入虚拟节点
		List<Integer> nodeposi = new ArrayList<Integer>();

		for (int i = 0; i < nodeMul; i++) {
			Integer posi = MD5Utils.GetMD5CodeToInt(nodeName + "-" + i);
			nodeposi.add(posi);
			nodes.put(posi, nodeName);
		}
		nodeposition.put(nodeName, nodeposi);
	}

	public void removeNode(String nodeName) {

		List<Integer> nodepos = nodeposition.get(nodeName);

		for (Integer posi : nodepos) {
			nodes.remove(posi);
		}
	}

	public String lookup(String key) {

		Integer keyPos = MD5Utils.GetMD5CodeToInt(key);
		Set<Integer> positions =nodes.keySet();
		System.out.println("keyMd5Pos     " + keyPos);
		// 默认先获取第一个节点
		String nodeName = nodes.get(nodes.firstKey());
		for (Integer posi : positions) {
			if (keyPos <= posi) {
				nodeName = nodes.get(posi);
				break;
			}
		}
		return nodeName;
	}

	public void printNodes() {
		Set<Integer> positions = nodes.keySet();
		for (Integer posi : positions) {
			System.out.println(nodes.get(posi) + "      " + posi);
		}
	}
}

package yuan;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/*
 * MD5 算法
 */
public class MD5Utils {

	public MD5Utils() {
	}

	// 返回形式只为数字
	private static int byteToInt(byte[] bByte) {

		int value = 0;
		// 由高位到低位
		for (int i = 0; i < 4; i++) {
			int shift = (4 - 1 - i) * 8;
			value += (bByte[i] & 0x000000FF) << shift;// 往高位游
		}
		return value;
	}

	public static int GetMD5CodeToInt(String strObj) {
		int result = 0;
		try {
			MessageDigest md = MessageDigest.getInstance("MD5");
			// md.digest() 该函数返回值为存放哈希值结果的byte数组
			result = byteToInt(md.digest(strObj.getBytes()));
		} catch (NoSuchAlgorithmException ex) {
			ex.printStackTrace();
		}
		return result;
	}
}

 3)简单调用:

   

package yuan;

public class Test {

	public static void main(String[] args) {

		ConsistentHash hash = new ConsistentHash();

		// 添加节点
		hash.addNode("a");
		hash.addNode("b");
		hash.addNode("c");

		// 打印所有的节点信息
		hash.printNodes();

		// 获取某个 key 的落点 即命中 那个节点
		String nodeName = hash.lookup("name");

		System.out.println(nodeName);

		System.out.println("==================================");

		// 移除节点
		hash.removeNode("a");

		hash.printNodes();
	}

}

  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值