`
BucketLi
  • 浏览: 195034 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
博客专栏
5a76a659-f8e6-3bf3-b39a-8ae8f7a0f9d9
Percolator与分布...
浏览量:5672
社区版块
存档分类
最新评论

一致性hash的实现

 
阅读更多
参照了dennis_zane同学的实现,并且测试了不同虚拟节点和不同hash算法对数据均衡度影响.hash算法实现参考前面的<java几个有用的Hash算法>一文
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

public class MyConsistHash {
	// 平均虚拟节点数
	int NUM_REPS = 160;
	HashAlgorithm alg = HashAlgorithm.KETAMA_HASH;

	public static byte[] computeMD5(final String k) {
		MessageDigest md5;
		try {
			md5 = MessageDigest.getInstance("MD5");
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException("MD5 not supported", e);
		}
		md5.reset();
		md5.update(k.getBytes());
		return md5.digest();
	}

	public TreeMap<Long, String> buildMacMap(final List<String> macIps) {
		final TreeMap<Long/* hash */, String/* macIp */> macMap = new TreeMap<Long, String>();
		for (String ip : macIps) {
			if (this.alg == HashAlgorithm.KETAMA_HASH) {
				for (int i = 0; i < NUM_REPS / 4; i++) {
					final byte[] digest = HashAlgorithm.computeMd5(ip + "-"
							+ 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;
						macMap.put(k, ip);
					}
				}
			} else {
				for (int i = 0; i < NUM_REPS; i++) {
					final long key = this.alg.hash(ip + "-" + i);
					macMap.put(key, ip);
				}
			}
		}
		return macMap;
	}
	
    public String findMacByKey(final TreeMap<Long, String> macMap, final String key) {
        final Long hash = this.alg.hash(key);
        Long target = hash;
        if (!macMap.containsKey(hash)) {
            target = macMap.ceilingKey(hash);
            if (target == null && !macMap.isEmpty()) {
                target = macMap.firstKey();
            }
        }
        final String targetMac = macMap.get(target);
        return targetMac;
    }
	
    public static void main(String[] args){
    	List<String> ips=new ArrayList<String>();
    	ips.add("10.232.0.2");
    	ips.add("10.232.0.3");
    	ips.add("10.232.0.4");
    	ips.add("10.232.0.5");
    	ips.add("10.232.0.6");
    	ips.add("10.232.0.27");
    	ips.add("10.232.0.28");
    	ips.add("10.232.0.68");
    	ips.add("10.232.0.97");
    	MyConsistHash hash=new MyConsistHash();
//    	hash.setNUM_REPS(1024);
//    	hash.setAlg(HashAlgorithm.CRC32_HASH);
    	TreeMap<Long,String> macMap=hash.buildMacMap(ips);
    	Map<String,Long> stat=new HashMap<String,Long>();
        long start=System.currentTimeMillis();
    	for(int i=0;i<100000;i++){
    		String ip=hash.findMacByKey(macMap, "a"+i);
    		Long count=stat.get(ip);
    		if(count==null){
    			stat.put(ip, new Long(0));
    		}else{
    			stat.put(ip, count+1);
    		}
    	}
        System.out.println(System.currentTimeMillis()-start);
    	
    	for(Map.Entry<String,Long> entry:stat.entrySet()){
    		System.out.println("mac:"+entry.getKey()+" hits:"+entry.getValue());
    	}
    }

	public void setAlg(HashAlgorithm alg) {
		this.alg = alg;
	}

	public void setNUM_REPS(int nUM_REPS) {
		NUM_REPS = nUM_REPS;
	}
}



使用默认KETAMA_HASH,
80个虚拟节点:254ms
mac:10.232.0.28 hits:10079
mac:10.232.0.68 hits:9699
mac:10.232.0.2 hits:10621
mac:10.232.0.3 hits:9798
mac:10.232.0.4 hits:13422
mac:10.232.0.5 hits:10045
mac:10.232.0.27 hits:10871
mac:10.232.0.6 hits:14791
mac:10.232.0.97 hits:10665

160个虚拟节点:265ms
mac:10.232.0.28 hits:12355
mac:10.232.0.68 hits:11182
mac:10.232.0.2 hits:11178
mac:10.232.0.3 hits:9750
mac:10.232.0.4 hits:12429
mac:10.232.0.5 hits:9641
mac:10.232.0.27 hits:10777
mac:10.232.0.6 hits:10610
mac:10.232.0.97 hits:12069

320个虚拟节点:249ms
mac:10.232.0.28 hits:11466
mac:10.232.0.68 hits:10064
mac:10.232.0.2 hits:11004
mac:10.232.0.3 hits:10186
mac:10.232.0.4 hits:11570
mac:10.232.0.5 hits:10740
mac:10.232.0.27 hits:11249
mac:10.232.0.6 hits:11324
mac:10.232.0.97 hits:12388

640个虚拟节点:245ms
mac:10.232.0.28 hits:10701
mac:10.232.0.68 hits:10978
mac:10.232.0.2 hits:11272
mac:10.232.0.3 hits:10566
mac:10.232.0.4 hits:11700
mac:10.232.0.5 hits:10512
mac:10.232.0.27 hits:11314
mac:10.232.0.6 hits:11541
mac:10.232.0.97 hits:11407

1024个虚拟节点:224 ms
mac:10.232.0.28 hits:11196
mac:10.232.0.68 hits:11198
mac:10.232.0.2 hits:11063
mac:10.232.0.3 hits:10930
mac:10.232.0.4 hits:11623
mac:10.232.0.5 hits:10448
mac:10.232.0.27 hits:11289
mac:10.232.0.6 hits:11508
mac:10.232.0.97 hits:10736


使用1024个虚拟节点,
CRC32_HASH:120ms
mac:10.232.0.28 hits:10668
mac:10.232.0.68 hits:13738
mac:10.232.0.2 hits:8805
mac:10.232.0.3 hits:10010
mac:10.232.0.4 hits:9525
mac:10.232.0.5 hits:10088
mac:10.232.0.6 hits:12162
mac:10.232.0.27 hits:10855
mac:10.232.0.97 hits:14140

KETAMA_HASH:227ms
mac:10.232.0.28 hits:11196
mac:10.232.0.68 hits:11198
mac:10.232.0.2 hits:11063
mac:10.232.0.3 hits:10930
mac:10.232.0.4 hits:11623
mac:10.232.0.5 hits:10448
mac:10.232.0.27 hits:11289
mac:10.232.0.6 hits:11508
mac:10.232.0.97 hits:10736

MYSQL_HASH:82ms
mac:10.232.0.28 hits:10119
mac:10.232.0.68 hits:13599
mac:10.232.0.2 hits:15329
mac:10.232.0.3 hits:16799
mac:10.232.0.4 hits:7199
mac:10.232.0.5 hits:10159
mac:10.232.0.27 hits:8519
mac:10.232.0.6 hits:3899
mac:10.232.0.97 hits:14369

ELECTION_HASH:243ms
mac:10.232.0.28 hits:11054
mac:10.232.0.68 hits:10554
mac:10.232.0.2 hits:11180
mac:10.232.0.3 hits:11092
mac:10.232.0.4 hits:11137
mac:10.232.0.5 hits:11519
mac:10.232.0.27 hits:10753
mac:10.232.0.6 hits:11412
mac:10.232.0.97 hits:11290

LUA_HASH:113ms
mac:10.232.0.28 hits:10950
mac:10.232.0.68 hits:11137
mac:10.232.0.2 hits:10783
mac:10.232.0.3 hits:11370
mac:10.232.0.4 hits:11143
mac:10.232.0.5 hits:10991
mac:10.232.0.27 hits:11645
mac:10.232.0.6 hits:11048
mac:10.232.0.97 hits:10924

NATIVE_HASH:81ms
mac:10.232.0.68 hits:89999
mac:10.232.0.2 hits:9999

...







分享到:
评论
3 楼 沙漠绿树 2015-01-15  
增加虚拟节点解决数据均衡的问题。我有个疑问:
1.使用虚拟节点后,但是当我增加物理节点后,环中的虚拟节点是否要增加,如果把他应用在mysql上,数据迁移是否会很困难?

2.在使用虚拟节点时,比如5个物理节点,每个物理节点虚拟出1024个虚节点,按道理hash环有5120个节点,但是使用kemata哈希虚拟环时,有些节点key的哈希结果相同,导致hash环中少于5120个节点?
2 楼 BucketLi 2012-08-23  
lyy3323 写道
大概看了一下。如果吧hash的具体算法再抽离出来更好。

前面有一篇<java几个有用的Hash算法>
1 楼 lyy3323 2012-08-06  
大概看了一下。如果吧hash的具体算法再抽离出来更好。

相关推荐

    一致性Hash简单实现

    在这个简单的实现中,我们将探讨如何用Java语言来模拟一致性哈希的工作原理。 1. **一致性哈希的基本概念** - **哈希环**:一致性哈希将所有可能的哈希值映射到一个闭合的圆环上,每个节点都按照哈希值分布在环上...

    C++实现一致性hash算法

    一致性hash应用于负载均衡算法,本实现由C++语言开发。 一致性hash算法提出了在动态变化的Cache环境中,判定哈希算法好坏的四个定义: 1、平衡性(Balance)2、单调性(Monotonicity) 3、分散性(Spread)4、负载(Load)

    一致性hashjava实现

    在这个Java实现中,我们看到的是Ketama一致性哈希算法,这是一种在实践中广泛应用的一致性哈希变体。 Ketama一致性哈希算法由Last.fm的工程师开发,其设计目标是优化分布式哈希表的性能,特别是在处理大量小键值对...

    一致性Hash算法的原理及实现

    ### 一致性Hash算法的原理及实现 #### 一、引言 一致性Hash算法是一种用于解决分布式环境下数据存储和检索问题的重要技术。它最初由David Karger等人在1997年的论文《Consistent Hashing and Random Trees: ...

    一致性哈希算法源码 Ketama一致性hash算法源码

    一致性哈希算法是一种分布式哈希(Distributed Hash Table, DHT)技术,旨在解决在分布式环境中数据分布不均匀的问题。Ketama算法是基于一致性哈希的一种优化实现,由Last.fm公司的Simon Willison提出,其目标是在...

    C/C++ 一致性hash算法

    一致性哈希算法是一种分布式哈希(Distributed Hash Table, DHT)技术,它在处理大量数据分布到多个节点上时,能保持较好的均衡性和可扩展性。在C/C++编程中,一致性哈希通常用于构建分布式系统,如负载均衡、缓存...

    memcache分布式一致性hash

    分布式一致性哈希是一种解决在分布式缓存系统中如何高效、稳定地分配数据的算法,尤其在Memcache等缓存服务中广泛应用。...在Memcache等分布式缓存服务中,一致性哈希是实现高效、可扩展性和稳定性的关键算法。

    一致性hash算法简介加C++实现

    一致性hash算法简介加C++实现

    Ketama一致性Hash算法(含Java代码) 1

    Ketama一致性哈希算法是基于一致性哈希的一种优化实现,主要解决了传统一致性哈希中节点分布不均匀的问题。在Ketama中,每个实际的物理服务器会被映射到多个虚拟节点,通常是100到200个,这些虚拟节点均匀分布在环上...

    解决分布式数据插入数据库~一致性hash算法

    为了解决这个问题,可以采用跳数法(Jump Consistent Hash)或者更高级的一致性哈希变体,如Ketama或libketama。哈希冲突则可以通过开放寻址、链地址法等方法来解决。 此外,一致性哈希算法在分布式缓存如Memcached...

    基于一致性Hash的分布式海量分子检索模型.pdf

    【基于一致性Hash的分布式海量分子检索模型】 在大数据环境下,传统的通用图匹配搜索方法面临着效率低下和无法快速定位折射率数据的问题。为了应对这一挑战,本文提出了一种基于一致性Hash的分布式海量分子检索模型...

    libconhash一致性hash

    在这个上下文中,`libconhash`是一个专门实现一致性哈希的C语言库,它为开发者提供了高效且易于使用的接口来处理分布式环境中的数据分布问题。 一致性哈希的基本思想是将数据和服务器映射到一个大的哈希环上。每个...

    一致性哈希算法C版实现

    在C语言实现一致性哈希时,我们需要理解以下几个核心概念: 1. **哈希函数**:一致性哈希首先依赖于哈希函数,将数据或服务器的标识映射到一个固定大小的环形空间上。通常使用模运算来实现这个过程,使得哈希值可以...

    对一致性Hash算法,Java代码实现的深入研究1

    对于Java实现一致性Hash算法,有几种可能的方法: 1. **排序+List**:首先,将所有服务器节点的哈希值放入一个数组,然后使用排序算法(如归并排序、快速排序等)对数组进行排序,再将排序后的结果放入List中。之后...

    Cluster和web模式问题笔记

    解决方案包括如Ketama、Voldemort等一致性Hash实现。 2. 集群时钟同步问题:在分布式系统中,保持所有节点的时钟同步至关重要,因为时间不一致可能导致数据冲突和错误决策。NTP(网络时间协议)是常见的时钟同步...

    一致性hash算法(c++)

    C++实现的一致性哈希库可以为开发人员提供方便的接口,直接编译成静态库或动态库,并包含示例程序帮助理解其用法。 在一致性哈希中,传统哈希函数将数据映射到固定数量的桶(例如0到2^32-1)上,但这种方法在增加或...

    SpringBoot_shardDB_shardTable:SpringBoot集成Sharding-JDBC实现分库分表,自定义分片算法,基于一致性hash算法,易于扩容

    一致性Hash算法,易于扩容;添加了 单元测试,使用Spring提供的RestTemplate调用RestFul风格的API接口;整合了 quartz 定时任务框架 ,并进行了封装,只需在构建完定时任务Job类后,在 application-quartz....

Global site tag (gtag.js) - Google Analytics