一致性哈希算法与Java实现

标签: 一致性 哈希 算法 | 发表时间:2014-07-22 17:28 | 作者:qqulijun
出处:http://www.iteye.com

一致性哈希算法是分布式系统中常用的算法。比如,一个分布式的存储系统,要将数据存储到具体的节点上,如果采用普通的hash方法,将数据映射到具体的节点上,如key%N,key是数据的key,N是机器节点数,如果有一个机器加入或退出这个集群,则所有的数据映射都无效了,如果是持久化存储则要做数据迁移,如果是分布式缓存,则其他缓存就失效了。

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

 

把数据用hash函数(如MD5),映射到一个很大的空间里,如图所示。数据的存储时,先得到一个hash值,对应到这个环中的每个位置,如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实现:

[java]  view plain copy print ?
  1. public class Shard<S> { // S类封装了机器节点的信息 ,如name、password、ip、port等   
  2.   
  3.     private TreeMap<Long, S> nodes; // 虚拟节点   
  4.     private List<S> shards; // 真实机器节点   
  5.     private final int NODE_NUM = 100; // 每个机器节点关联的虚拟节点个数   
  6.   
  7.     public Shard(List<S> shards) {  
  8.         super();  
  9.         this.shards = shards;  
  10.         init();  
  11.     }  
  12.   
  13.     private void init() { // 初始化一致性hash环   
  14.         nodes = new TreeMap<Long, S>();  
  15.         for (int i = 0; i != shards.size(); ++i) { // 每个真实机器节点都需要关联虚拟节点   
  16.             final S shardInfo = shards.get(i);  
  17.   
  18.             for (int n = 0; n < NODE_NUM; n++)  
  19.                 // 一个真实机器节点关联NODE_NUM个虚拟节点   
  20.                 nodes.put(hash("SHARD-" + i + "-NODE-" + n), shardInfo);  
  21.   
  22.         }  
  23.     }  
  24.   
  25.     public S getShardInfo(String key) {  
  26.         SortedMap<Long, S> tail = nodes.tailMap(hash(key)); // 沿环的顺时针找到一个虚拟节点   
  27.         if (tail.size() == 0) {  
  28.             return nodes.get(nodes.firstKey());  
  29.         }  
  30.         return tail.get(tail.firstKey()); // 返回该虚拟节点对应的真实机器节点的信息   
  31.     }  
  32.   
  33.     /** 
  34.      *  MurMurHash算法,是非加密HASH算法,性能很高, 
  35.      *  比传统的CRC32,MD5,SHA-1(这两个算法都是加密HASH算法,复杂度本身就很高,带来的性能上的损害也不可避免) 
  36.      *  等HASH算法要快很多,而且据说这个算法的碰撞率很低. 
  37.      *  http://murmurhash.googlepages.com/ 
  38.      */  
  39.     private Long hash(String key) {  
  40.           
  41.         ByteBuffer buf = ByteBuffer.wrap(key.getBytes());  
  42.         int seed = 0x1234ABCD;  
  43.           
  44.         ByteOrder byteOrder = buf.order();  
  45.         buf.order(ByteOrder.LITTLE_ENDIAN);  
  46.   
  47.         long m = 0xc6a4a7935bd1e995L;  
  48.         int r = 47;  
  49.   
  50.         long h = seed ^ (buf.remaining() * m);  
  51.   
  52.         long k;  
  53.         while (buf.remaining() >= 8) {  
  54.             k = buf.getLong();  
  55.   
  56.             k *= m;  
  57.             k ^= k >>> r;  
  58.             k *= m;  
  59.   
  60.             h ^= k;  
  61.             h *= m;  
  62.         }  
  63.   
  64.         if (buf.remaining() > 0) {  
  65.             ByteBuffer finish = ByteBuffer.allocate(8).order(  
  66.                     ByteOrder.LITTLE_ENDIAN);  
  67.             // for big-endian version, do this first:   
  68.             // finish.position(8-buf.remaining());   
  69.             finish.put(buf).rewind();  
  70.             h ^= finish.getLong();  
  71.             h *= m;  
  72.         }  
  73.   
  74.         h ^= h >>> r;  
  75.         h *= m;  
  76.         h ^= h >>> r;  
  77.   
  78.         buf.order(byteOrder);  
  79.         return h;  
  80.     }  
  81.   
  82. }  


已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [一致性 哈希 算法] 推荐:

一致性哈希算法 - Consistent Hashing

- - CSDN博客云计算推荐文章
一、简单介绍一致性哈希算法.         分布式存储中,常常涉及到负载均衡问题,由于有多个数据存储服务器. 因此当一个对象被保存时候,它究竟应该存放到哪个数据存储服务器上面呢.         又例如:现在假设有一个网站,最近发现随着流量增加,服务器压力越来越大,之前直接读写数据库的方式已经不能满足用户的访问,于是想引入 Memcached 作为缓存机制.

一致性哈希算法(consistent hashing)

- - 互联网 - ITeye博客
consistent hashing由来. 在麻省理工学院用作分布式缓存,现在已经扩大到其他领域. 它被设计来解决hash的什么问题. 假设有m个对象需要被映射到n个node上,简单hash就求余映射hash(object)%n->node,就大致均匀的分布到n个node上了. 可是问题在于如果n发生变化(多了或者少了),就必须重新计算保存对象存放到node,这代价未免有点大.

“分布式哈希”和“一致性哈希”的概念与算法实现

- Wolf - 搜索研发部官方博客
  分布式哈希和一致性哈希是分布式存储和p2p网络中说的比较多的两个概念了. 介绍的论文很多,这里做一个入门性质的介绍.   两个key point:每个节点只维护一部分路由;每个节点只存储一部分数据. 从而实现整个网络中的寻址和存储. DHT只是一个概念,提出了这样一种网络模型. 并且说明它是对分布式存储很有好处的.

一致性哈希算法与Java实现

- - Java - 编程语言 - ITeye博客
一致性哈希算法是分布式系统中常用的算法. 比如,一个分布式的存储系统,要将数据存储到具体的节点上,如果采用普通的hash方法,将数据映射到具体的节点上,如key%N,key是数据的key,N是机器节点数,如果有一个机器加入或退出这个集群,则所有的数据映射都无效了,如果是持久化存储则要做数据迁移,如果是分布式缓存,则其他缓存就失效了.

一致性哈希算法及其在分布式系统中的应用

- BeerBubble - 博客园-EricZhang&#39;s Technology Blog
本文将会从实际应用场景出发,介绍一致性哈希算法(Consistent Hashing)及其在分布式系统中的应用. 首先本文会描述一个在日常开发中经常会遇到的问题场景,借此介绍一致性哈希算法以及这个算法如何解决此问题;接下来会对这个算法进行相对详细的描述,并讨论一些如虚拟节点等与此算法应用相关的话题.

一个速度快内存占用小的一致性哈希算法

- - 鸟窝
这篇论文中提出在动态变化的Cache环境中,哈希算法应该满足的4个适应条件::Balance(均衡)、Monotonicity(单调性)、Spread(分散性)、Load(负载). 在分布式缓存系统中使用一致性哈希算法时,某个节点的添加和移除不会重新分配全部的缓存,而只会影响小部分的缓存系统,如果均衡性做的好的话,当添加一个节点时,会均匀地从其它节点移一部分缓存到新的节点上;当删除一个节点的时候,这个节点上的缓存会均匀地分配到其它活着的节点上.

_00013 一致性哈希算法 Consistent Hashing 探讨以及相应的新问题出现解决

- - CSDN博客云计算推荐文章
一般通常会想到的就是哈希取余了吧. 也就是 Hash(userid)% N (N=12),这样的话也能适当的减小很多压力了,但是这样的话又会产生一些新的问题,增加节点跟减少节点 :. 假如有一台Redis服务器挂掉了,那么是否这样 Hash(userid)% N (N=12) 哈希取余到该Redis的数据会全部丢失呢.

一致性HASH算法

- - 企业架构 - ITeye博客
一致性 hash 算法( consistent hashing ). consistent hashing 算法早在 1997 年就在论文 . Consistent hashing and random trees 中被提出,目前在cache 系统中应用越来越广泛;. 比如你有 N 个 cache 服务器(后面简称 cache ),那么如何将一个对象 object 映射到 N 个 cache 上呢,你很可能会采用类似下面的通用方法计算 object 的 hash 值,然后均匀的映射到到 N 个 cache ;.

利用一致性哈希水平拆分MySql单表

- - snoopyxdy的博客
Sharding(切片) 不是一门新技术,而是一个相对简朴的软件理念,就是当我们的数据库单机无法承受高强度的i/o时,我们就考虑利用 sharding 来把这种读写压力分散到各个主机上去. 所以Sharding 不是一个某个特定数据库软件附属的功能,而是在具体技术细节之上的抽象处理,是Horizontal Partitioning 水平扩展(或横向扩展)的解决方案,其主要目的是为突破单节点数据库服务器的 I/O 能力限制,注意这里是突破单点数据库服务器的“I/O”能力.

一致性Hash算法背景(转)

- - 开源软件 - ITeye博客
一致性哈希算法在1997年由麻省理工学院的Karger等人在解决分布式Cache中提出的,设计目标是为了解决因特网中的热点(Hot spot)问题,初衷和CARP十分类似. 一致性哈希修正了CARP使用的简单哈希算法带来的问题,使得DHT可以在P2P环境中真正得到应用.   但现在一致性hash算法在分布式系统中也得到了广泛应用,研究过memcached缓存数据库的人都知道,memcached服务器端本身不提供分布式cache的一致性,而是由客户端来提供,具体在计算一致性hash时采用如下步骤:.