首页 > 编程知识 正文

一致性hash算法实现,哈希排序算法原理

时间:2023-05-04 21:18:35 阅读:165373 作者:4189

一致性哈希算法是分布式系统中常用的算法。 例如,在一个分布式存储系统中,为了将数据存储在特定节点上,使用普通的hash方法将数据映射到特定节点。 例如,key%N,key是数据的key,n是计算机节点数,如果有一台计算机加入或退出此群集,则所有数据映射都将被禁用。 对于持久化存储,执行数据迁移;对于分布式缓存,执行其他缓存

因此,引入了一致性哈希算法:

使用hash函数(例如MD5 )将数据映射到如图所示的大空间。 的数据保存时,首先得到哈希值,对应于环中的每个位置。 例如,k1对应于图中的位置,顺时针找到机器节点b,将k1保存在名为b的节点中。

如果B节点断开,B上的数据将落入C节点,如下图所示。

这样,只影响c节点,而不影响其它节点a、d的数据。 但是,这也会导致“雪崩”,因为c节点承担着b节点的数据,c节点的负荷变大,c节点也容易停机,这样下去整个集群就会挂起。

为此,引入了“虚拟节点”的概念。 也就是说,想象这个环上有很多“虚拟节点”。 数据存储在环中顺时针查找虚拟节点,每个虚拟节点与实际节点相关联。 在下图中使用。

图中的A1、A2、B1、B2、C1、C2、D1、D2都是虚拟节点,机器a加载并保存A1、A2的数据,机器b加载并保存B1、B2的数据,机器c加载并保存C1、C2的数据。 由于这些虚拟节点数量多且分布均匀,所以不会发生“雪崩”现象。

Java实现:

publicclassShard{//S类封装了机器节点的信息,如name、password、ip和port

privateTreeMapnodes; //虚拟节点

privateListshards; //实际机器节点

privatefinalintNODE_NUM=100; //每个计算机节点相关的虚拟节点数

公共硬件(list shards ) {

super (;

this.shards=shards;

init (;

}

privatevoidinit ()//初始化一致的哈希

nodes=newTreeMap (;

for(inti=0; I!=shards.size (; I )//每个实际计算机节点必须与一个虚拟节点相关联

finalsshardinfo=Shards.get(I;

for(intn=0; n

//将NODE_NUM个虚拟节点与一个实际的机器节点相关联

nodes.put(hash )、shard-'I'-node-'n )、shardInfo );

}

}

publicsgetshardinfo(stringkey ) {

sortedmaptail=nodes.tail map (hash (key ) ); //顺时针找到虚拟节点

if(tail.size ()==0) {

returnnodes.get(nodes.firstkey );

}

returntail.get(tail.firstkey ); //返回与该虚拟节点对应实际机器节点的信息

}

//*

*MurMurHash算法是一种非加密HASH算法,性能高。

*与传统的CRC32、MD5和SHA-1相比((这两种算法都是加密散列算法,复杂性本身较高,性能下降也是不可避免的) ) ) ) )。

据说等待HASH算法要快得多,而且这个算法的冲突率很低。

* http://murmur hash.Google pages.com /

*/

privatelonghash(stringkey ) {

bytebufferbuf=byte buffer.wrap (key.getbytes () );

intseed=0x1234ABCD;

ByteOrderbyteOrder=buf.order (;

buf.order (byteorder.little _ endian );

longm=0xc6a4a7935bd1e995L;

intr=47;

Longh=seed^(buf.remaining () *m );

长;

while(buf.remaining () )=8) {

k=buf.getLong (;

k*=m;

k^=kr;

k*=m;

h^=k;

h*=m;

}

if(buf.remaining) ) ) )。

bytebufferfinish=byte buffer.allocate (8).order (

ByteOrder.LITTLE_ENDIAN;

//forbig-endianversion,dothisfirst:

//finish.position (8- buf.remaining ) );

finish.put(buf ).rewind );

h^=finish.getLong (;

h*=m;

}

h^=hr;

h*=m;

h^=hr;

BUF.order(byteorder );

返回;

}

}

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。