一致哈希算法 Ketama

本文深入探讨了一致哈希算法的设计原则与实现细节,重点介绍了如何通过创建虚拟节点来均衡数据分布,避免节点增减引起的大量数据迁移。同时,文章提供了具体的代码示例,展示了如何为每个实际节点生成多个虚拟节点,以及如何利用MD5算法确保虚拟节点的唯一性和分布的均匀性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一致哈希算法要求
节点数量的增加 要能够保证旧的数据能够按照老的算法 环形
减少映射关系的变动
所以不能安装数量来hash求余之类的操作
否者将会导致大量的节点数据失效和迁移

一致哈希算法设计标准
再不改边原有映射关系的前提下 将数据均匀分流的其他节点
(创建虚拟节点 再导流到下一个节点 但是会有雪崩的危险)

	protected void setKetamaNodes(List<String> nodes) {

        //为每个节点生成100个虚拟节点  应为nodes是list 所以可以重复 后面计算虚拟节点的时候 应该避免碰撞
		final TreeMap<Long, String> newNodeMap = new TreeMap<Long, String>();
		final Set<String> newNodeSet = new HashSet<String>();
		final Map<String, Integer> nodeCounts = new TreeMap<String, Integer>();
		//一百个虚拟节点
		final int numReps = DEFAULT_REPETITIONS;
		for (final String node : nodes) {
			if (node == null) { throw new InvalidParameterException("Nodes may not be NULL."); }
			
			//加权节点 其实就是相同节点生成多份虚拟节点 而生成虚拟节点主要根据node生成 那就给node再拼接一个数量就ok了
			final int nodeCount = nodeCounts.containsKey(node) ? nodeCounts.get(node).intValue() + 1 : 1;
			final String nodePlusCount = decorateWithCounter(node, nodeCount);
		   //添加相同节点的数量
			nodeCounts.put(node, nodeCount);
			
			//nodes转存到set里面 应为会有重复
			newNodeSet.add(node);
			
			//每个节点分配100个虚拟节点 除以4 是为了充分利用MD5生成的长度为16的字节数组 这个数组生成4个long 正好给一组虚拟节点作为key 
			 *不直接遍历100个 然后取Md5的后4个字节 可能因为碰撞更小吧*

			拆分4个一组  然后每组再生成4个key  最后再不发生key碰撞的情况下  每个节点的虚拟节点还是100
			for (int i = 0; i < numReps / 4; i++) {
				final byte[] digest = computeMd5(decorateWithCounter(nodePlusCount, i));
				for (int h = 0; h < 4; h++) {
					final Long k = ((long) (digest[3 + h * 4] & 0xFF) << 24)
							| ((long) (digest[2 + h * 4] & 0xFF) << 16)
							| ((long) (digest[1 + h * 4] & 0xFF) << 8)
							| (digest[h * 4] & 0xFF);
					newNodeMap.put(k, node);
				}
			}
		}
		//断言 小于1000 key碰撞 则抛异常  测试环境
		assert newNodeSet.size() < 1000 ? newNodeMap.size() == numReps * nodes.size() : true : "Size: " + newNodeMap.size() + ", expected: " + (numReps * nodes.size());
		data = new KetamaData(newNodeMap, newNodeSet);
	}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值