<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    我的Java路上那些事兒

    快樂成長(zhǎng)
    posts - 110, comments - 101, trackbacks - 0, articles - 7
      BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理
      一致性哈希算法是分布式系統(tǒng)中常用的算法。比如,一個(gè)分布式的存儲(chǔ)系統(tǒng),要將數(shù)據(jù)存儲(chǔ)到具體的節(jié)點(diǎn)上,如果采用普通的hash方法,將數(shù)據(jù)映射到具體的節(jié)點(diǎn)上,如key%N,key是數(shù)據(jù)的key,N是機(jī)器節(jié)點(diǎn)數(shù),如果有一個(gè)機(jī)器加入或退出這個(gè)集群,則所有的數(shù)據(jù)映射都無(wú)效了,如果是持久化存儲(chǔ)則要做數(shù)據(jù)遷移,如果是分布式緩存,則其他緩存就失效了。

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


     

    把數(shù)據(jù)用hash函數(shù)(如MD5),映射到一個(gè)很大的空間里,如圖所示。數(shù)據(jù)的存儲(chǔ)時(shí),先得到一個(gè)hash值,對(duì)應(yīng)到這個(gè)環(huán)中的每個(gè)位置,如k1對(duì)應(yīng)到了圖中所示的位置,然后沿順時(shí)針找到一個(gè)機(jī)器節(jié)點(diǎn)B,將k1存儲(chǔ)到B這個(gè)節(jié)點(diǎn)中。

    如果B節(jié)點(diǎn)宕機(jī)了,則B上的數(shù)據(jù)就會(huì)落到C節(jié)點(diǎn)上,如下圖所示:


     

    這樣,只會(huì)影響C節(jié)點(diǎn),對(duì)其他的節(jié)點(diǎn)A,D的數(shù)據(jù)不會(huì)造成影響。然而,這又會(huì)造成一個(gè)“雪崩”的情況,即C節(jié)點(diǎn)由于承擔(dān)了B節(jié)點(diǎn)的數(shù)據(jù),所以C節(jié)點(diǎn)的負(fù)載會(huì)變高,C節(jié)點(diǎn)很容易也宕機(jī),這樣依次下去,這樣造成整個(gè)集群都掛了。

           為此,引入了“虛擬節(jié)點(diǎn)”的概念:即把想象在這個(gè)環(huán)上有很多“虛擬節(jié)點(diǎn)”,數(shù)據(jù)的存儲(chǔ)是沿著環(huán)的順時(shí)針方向找一個(gè)虛擬節(jié)點(diǎn),每個(gè)虛擬節(jié)點(diǎn)都會(huì)關(guān)聯(lián)到一個(gè)真實(shí)節(jié)點(diǎn),如下圖所使用:


    圖中的A1、A2、B1、B2、C1、C2、D1、D2都是虛擬節(jié)點(diǎn),機(jī)器A負(fù)載存儲(chǔ)A1、A2的數(shù)據(jù),機(jī)器B負(fù)載存儲(chǔ)B1、B2的數(shù)據(jù),機(jī)器C負(fù)載存儲(chǔ)C1、C2的數(shù)據(jù)。由于這些虛擬節(jié)點(diǎn)數(shù)量很多,均勻分布,因此不會(huì)造成“雪崩”現(xiàn)象。

     

    Java實(shí)現(xiàn):

    1. public class Shard<S> { // S類封裝了機(jī)器節(jié)點(diǎn)的信息 ,如name、password、ip、port等   
    2.   
    3.     private TreeMap<Long, S> nodes; // 虛擬節(jié)點(diǎn)   
    4.     private List<S> shards; // 真實(shí)機(jī)器節(jié)點(diǎn)   
    5.     private final int NODE_NUM = 100// 每個(gè)機(jī)器節(jié)點(diǎn)關(guān)聯(lián)的虛擬節(jié)點(diǎn)個(gè)數(shù)   
    6.   
    7.     public Shard(List<S> shards) {  
    8.         super();  
    9.         this.shards = shards;  
    10.         init();  
    11.     }  
    12.   
    13.     private void init() { // 初始化一致性hash環(huán)   
    14.         nodes = new TreeMap<Long, S>();  
    15.         for (int i = 0; i != shards.size(); ++i) { // 每個(gè)真實(shí)機(jī)器節(jié)點(diǎn)都需要關(guān)聯(lián)虛擬節(jié)點(diǎn)   
    16.             final S shardInfo = shards.get(i);  
    17.   
    18.             for (int n = 0; n < NODE_NUM; n++)  
    19.                 // 一個(gè)真實(shí)機(jī)器節(jié)點(diǎn)關(guān)聯(lián)NODE_NUM個(gè)虛擬節(jié)點(diǎn)   
    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)); // 沿環(huán)的順時(shí)針找到一個(gè)虛擬節(jié)點(diǎn)   
    27.         if (tail.size() == 0) {  
    28.             return nodes.get(nodes.firstKey());  
    29.         }  
    30.         return tail.get(tail.firstKey()); // 返回該虛擬節(jié)點(diǎn)對(duì)應(yīng)的真實(shí)機(jī)器節(jié)點(diǎn)的信息   
    31.     }  
    32.   
    33.     /** 
    34.      *  MurMurHash算法,是非加密HASH算法,性能很高, 
    35.      *  比傳統(tǒng)的CRC32,MD5,SHA-1(這兩個(gè)算法都是加密HASH算法,復(fù)雜度本身就很高,帶來(lái)的性能上的損害也不可避免) 
    36.      *  等HASH算法要快很多,而且據(jù)說(shuō)這個(gè)算法的碰撞率很低. 
    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. }  

    評(píng)論

    # re: 一致性哈希算法與Java實(shí)現(xiàn)   回復(fù)  更多評(píng)論   

    2014-05-22 12:25 by xdemo
    絕不可能~

    # re: 一致性哈希算法與Java實(shí)現(xiàn)   回復(fù)  更多評(píng)論   

    2014-08-12 17:37 by nodexy
    1樓高見?

    # re: 一致性哈希算法與Java實(shí)現(xiàn)   回復(fù)  更多評(píng)論   

    2015-01-15 20:37 by 沙漠綠樹
    我的qq是29561416

    我看了網(wǎng)上清一色都是拿memcached來(lái)說(shuō)一致性hash,增加虛擬節(jié)點(diǎn)解決數(shù)據(jù)均衡的問題。我有個(gè)疑問:
    1.使用虛擬節(jié)點(diǎn)后,但是當(dāng)我增加物理節(jié)點(diǎn)后,環(huán)中的虛擬節(jié)點(diǎn)是否要增加,如果把他應(yīng)用在mysql上,數(shù)據(jù)遷移是否會(huì)很困難?

    2.在使用虛擬節(jié)點(diǎn)時(shí),比如5個(gè)物理節(jié)點(diǎn),每個(gè)物理節(jié)點(diǎn)虛擬出1024個(gè)虛節(jié)點(diǎn),按道理hash環(huán)有5120個(gè)節(jié)點(diǎn),但是使用kemata哈希虛擬環(huán)時(shí),有些節(jié)點(diǎn)key的哈希結(jié)果相同,導(dǎo)致hash環(huán)中少于5120個(gè)節(jié)點(diǎn)?

    # re: 一致性哈希算法與Java實(shí)現(xiàn)   回復(fù)  更多評(píng)論   

    2015-10-21 00:22 by 一個(gè)不起眼的攻城獅
    我來(lái)解決樓上的問題,解決之前賢說(shuō)兩句:
    樓上太強(qiáng)勢(shì),絕對(duì)不可能,這5個(gè)字震懾到我了,而且看你的提問,只能算是懂一點(diǎn)hash一致性算法,樓主的說(shuō)法是正確的,也是非常有參考價(jià)值的。
    問題答案如下:
    1. 你所說(shuō)的是hash一致性的數(shù)據(jù)遷移問題,這個(gè)是hash一致性的弱點(diǎn),可以改進(jìn),但是需要自己開發(fā)相應(yīng)的程序,不是不可能完成的而是可以完成的,只是復(fù)雜點(diǎn);退一萬(wàn)步,任何技術(shù)都不是萬(wàn)能的,都有弊端,只是看你的業(yè)務(wù)需求最適于那種技術(shù)。
    2. 你這個(gè)可以將hash的空間編程2的32次方,2的64次方都可以,不是只能用一種,要活學(xué)活用。另外,hash出來(lái)的key值相同少有發(fā)生,這是hash的特性決定的,也就是hash沖突,這個(gè)倒是個(gè)問題,解決方法是bloomfilter算法,有興趣的可以自己去查。

    # re: 一致性哈希算法與Java實(shí)現(xiàn)   回復(fù)  更多評(píng)論   

    2016-07-25 12:04 by 三單聯(lián)咖啡色
    有一個(gè)問題,如果使用虛擬節(jié)點(diǎn),某臺(tái)機(jī)器每次宕機(jī)再恢復(fù)后都需要遷移數(shù)據(jù)。這樣是否反而更麻煩了。

    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 亚洲色中文字幕在线播放| 亚洲一区二区三区在线| 国产亚洲综合久久| 国产高清免费的视频| 亚洲国产视频久久| 好大好硬好爽免费视频| 亚洲日韩亚洲另类激情文学| 91黑丝国产线观看免费| 亚洲国产精品午夜电影| 18国产精品白浆在线观看免费| 久久夜色精品国产噜噜噜亚洲AV | 国产亚洲精彩视频| avtt亚洲天堂| eeuss影院免费直达入口| 亚洲伊人久久精品影院| 久久精品国产影库免费看| 亚洲色图国产精品| 国产成人午夜精品免费视频| 亚洲人成网站色7799| 免费人成在线观看视频播放| 亚欧国产一级在线免费| 亚洲国产高清视频| 在线天堂免费观看.WWW| 久久综合亚洲色hezyo| 亚洲毛片网址在线观看中文字幕| GOGOGO高清免费看韩国| 97亚洲熟妇自偷自拍另类图片| 国产又大又粗又长免费视频| 亚洲日本成本人观看| 亚洲另类激情专区小说图片| a在线观看免费视频| 亚洲一线产区二线产区精华| 日本免费中文字幕在线看| 大妹子影视剧在线观看全集免费| 亚洲欧洲在线观看| 在线播放免费人成视频在线观看| xxxx日本在线播放免费不卡| 亚洲国产精品一区| 国产视频精品免费| 成全视频高清免费观看电视剧| 亚洲精品免费在线|