一致性hash算法 java代码实现与测试

写了一个一致性hash的java实现代码,算法是用别人的,据说很好,然后自己做了一个测试,用线程池起了1000个线程,每个线程hash10000次,模拟一万次数据hash,并将测试结果上传。

/**
 * 一致性hash代码
 * 
 * @author shiguiming
 *
 * @param <T>
 */
public class Shared<T> {

	// 真实节点对应的虚拟节点数量
	private int length = 100;
	// 虚拟节点信息
	private TreeMap<Long, T> virtualNodes;
	// 真实节点信息
	private List<T> realNodes;

	public Shared(List<T> realNodes) {
		this.realNodes = realNodes;
		init();
	}

	public List<T> getReal() {
		return realNodes;
	}

	/**
	 * 初始化虚拟节点
	 */
	private void init() {
		virtualNodes = new TreeMap<Long, T>();
		for (int i = 0; i < realNodes.size(); i++) {
			for (int j = 0; j < length; j++) {
				virtualNodes.put(hash("aa" + i + j), realNodes.get(i));
			}
		}
	}

	/**
	 * 获取一个结点
	 * 
	 * @param key
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public T getNode(String key) {
		Long hashedKey = hash(key);
		// TODO judge null
		Entry en = virtualNodes.ceilingEntry(hashedKey);
		if (en == null) {
			return (T) virtualNodes.firstEntry().getValue();
		}
		return (T) en.getValue();
	}

	/**
	 * MurMurHash算法,是非加密HASH算法,性能很高,
	 * 比传统的CRC32,MD5,SHA-1(这两个算法都是加密HASH算法,复杂度本身就很高,带来的性能上的损害也不可避免)
	 * 等HASH算法要快很多,而且据说这个算法的碰撞率很低. http://murmurhash.googlepages.com/
	 */
	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);
			// for big-endian version, do this first:
			// finish.position(8-buf.remaining());
			finish.put(buf).rewind();
			h ^= finish.getLong();
			h *= m;
		}

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

		buf.order(byteOrder);
		return h;
	}

	/**
	 * 测试内部类
	 * 
	 * @author shiguiming
	 *
	 */
	static public class Node {
		private int name;
		private int count = 0;

		public Node() {

		}

		public Node(int i) {
			this.name = i;
		}

		public int getName() {
			return name;
		}

		public void setName(int name) {
			this.name = name;
		}

		public int getCount() {
			return count;
		}

		// 同步方法,防止并发
		synchronized public void inc() {
			count++;
		}

	}

	/**
	 * 测试方法
	 * 
	 * @param args
	 * @throws InterruptedException
	 */
	public static void main(String[] args) throws InterruptedException {
		List<Node> ndList = new ArrayList<Node>();
		int i = 0;
		while (true) {
			ndList.add(new Node(i));
			if (i++ == 9)
				break;
		}

		final Shared<Node> sh = new Shared<Node>(ndList);
		ExecutorService es = Executors.newCachedThreadPool();
		final CountDownLatch cdl = new CountDownLatch(1000);
		// 1000个线程
		for (int j = 0; j < 1000; j++) {
			es.execute(new Runnable() {

				@Override
				public void run() {
					// Random rd = new Random(1100);
					for (int k = 0; k < 10000; k++) {
						sh.getNode(String.valueOf(Math.random())).inc();
					}
					cdl.countDown();
				}
			});
		}

		// 等待所有线程结束
		cdl.await();
		List<Node> nodeList = sh.getReal();
		for (Node node : nodeList) {
			System.out.println("node" + node.getName() + ":" + node.getCount());
		}

	}
}

测试结果:


一共10,000,000次 hash,基本算是较均匀投递到10个节点,有什么问题大家交流~


  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
一致性哈希是一种常见的分布式哈希算法,主要用于解决缓存、负载均衡、分布式数据库等领域的问题。下面是一个简单的 Java 代码实现一致性哈希算法的示例: ```java import java.util.*; public class ConsistentHash { private final SortedMap<Integer, String> circle = new TreeMap<>(); private final int virtualNodes; public ConsistentHash(int virtualNodes, Collection<String> nodes) { this.virtualNodes = virtualNodes; for (String node : nodes) { addNode(node); } } public void addNode(String node) { for (int i = 0; i < virtualNodes; i++) { String virtualNode = node + "#" + i; int hash = getHash(virtualNode); circle.put(hash, node); } } public void removeNode(String node) { for (int i = 0; i < virtualNodes; i++) { String virtualNode = node + "#" + i; int hash = getHash(virtualNode); circle.remove(hash); } } public String getNode(String key) { if (circle.isEmpty()) { return null; } int hash = getHash(key); if (!circle.containsKey(hash)) { SortedMap<Integer, String> tailMap = circle.tailMap(hash); hash = tailMap.isEmpty() ? circle.firstKey() : tailMap.firstKey(); } return circle.get(hash); } private int getHash(String key) { // TODO: 实现自己的哈希算法 return key.hashCode(); } } ``` 上述代码中,我们通过 `SortedMap` 维护了一个环形空间,并将每个节点对应的虚拟节点散落在这个空间上。在查找节点时,首先计算出键值的哈希值,然后查找距离这个哈希值最近的节点。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值