国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

什么是一致性Hash算法?

feng409 / 3019人閱讀

摘要:五一致性算法的容錯性和可擴展性現假設不幸宕機,可以看到此時對象不會受到影響,只有對象被重定位到。綜上所述,一致性算法對于節點的增減都只需重定位環空間中的一小部分數據,具有較好的容錯性和可擴展性。

最近有小伙伴跑過來問什么是Hash一致性算法,說面試的時候被問到了,因為不了解,所以就沒有回答上,問我有沒有相應的學習資料推薦,當時上班,沒時間回復,晚上回去了就忘了這件事,今天突然看到這個,加班為大家整理一下什么是Hash一致性算法,希望對大家有幫助!文末送書,長按抽獎助手小程序即可參與,祝君好運!

經常閱讀我文章的小伙伴應該都很熟悉我寫文章的套路,上來就是先要問一句為什么?也就是為什么要有Hash一致性算法?就像以前介紹為什么要有Spring一樣,首先會以歷史的角度或者項目發展的角度來分析,今天的分享還是一樣的套路,先從歷史的角度來一步步分析,探討一下到底什么是Hash一致性算法!

一、Redis集群的使用
我們在使用Redis的時候,為了保證Redis的高可用,提高Redis的讀寫性能,最簡單的方式我們會做主從復制,組成Master-Master或者Master-Slave的形式,或者搭建Redis集群,進行數據的讀寫分離,類似于數據庫的主從復制和讀寫分離。如下所示:??

同樣類似于數據庫,當單表數據大于500W的時候需要對其進行分庫分表,當數據量很大的時候(標準可能不一樣,要看Redis服務器容量)我們同樣可以對Redis進行類似的操作,就是分庫分表。

假設,我們有一個社交網站,需要使用Redis存儲圖片資源,存儲的格式為鍵值對,key值為圖片名稱,value為該圖片所在文件服務器的路徑,我們需要根據文件名查找該文件所在文件服務器上的路徑,數據量大概有2000W左右,按照我們約定的規則進行分庫,規則就是隨機分配,我們可以部署8臺緩存服務器,每臺服務器大概含有500W條數據,并且進行主從復制,示意圖如下:

由于規則是隨機的,所有我們的一條數據都有可能存儲在任何一組Redis中,例如上圖我們用戶查找一張名稱為”a.png”的圖片,由于規則是隨機的,我們不確定具體是在哪一個Redis服務器上的,因此我們需要進行1、2、3、4,4次查詢才能夠查詢到(也就是遍歷了所有的Redis服務器),這顯然不是我們想要的結果,有了解過的小伙伴可能會想到,隨機的規則不行,可以使用類似于數據庫中的分庫分表規則:按照Hash值、取模、按照類別、按照某一個字段值等等常見的規則就可以出來了!好,按照我們的主題,我們就使用Hash的方式。

二、為Redis集群使用Hash
可想而知,如果我們使用Hash的方式,每一張圖片在進行分庫的時候都可以定位到特定的服務器,示意圖如下:

上圖中,假設我們查找的是”a.png”,由于有4臺服務器(排除從庫),因此公式為hash(a.png) % 4 = 2?,可知定位到了第2號服務器,這樣的話就不會遍歷所有的服務器,大大提升了性能!

三、使用Hash的問題
上述的方式雖然提升了性能,我們不再需要對整個Redis服務器進行遍歷!但是,使用上述Hash算法進行緩存時,會出現一些缺陷,主要體現在服務器數量變動的時候,所有緩存的位置都要發生改變!

試想一下,如果4臺緩存服務器已經不能滿足我們的緩存需求,那么我們應該怎么做呢?很簡單,多增加幾臺緩存服務器不就行了!假設:我們增加了一臺緩存服務器,那么緩存服務器的數量就由4臺變成了5臺。那么原本hash(a.png) % 4 = 2?的公式就變成了hash(a.png) % 5 = ??, 可想而知這個結果肯定不是2的,這種情況帶來的結果就是當服務器數量變動時,所有緩存的位置都要發生改變!換句話說,當服務器數量發生改變時,所有緩存在一定時間內是失效的,當應用無法從緩存中獲取數據時,則會向后端數據庫請求數據(還記得上一篇的《緩存雪崩》嗎?)!

同樣的,假設4臺緩存中突然有一臺緩存服務器出現了故障,無法進行緩存,那么我們則需要將故障機器移除,但是如果移除了一臺緩存服務器,那么緩存服務器數量從4臺變為3臺,也是會出現上述的問題!

所以,我們應該想辦法不讓這種情況發生,但是由于上述Hash算法本身的緣故,使用取模法進行緩存時,這種情況是無法避免的,為了解決這些問題,Hash一致性算法(一致性Hash算法)誕生了!

四、一致性Hash算法的神秘面紗
一致性Hash算法也是使用取模的方法,只是,剛才描述的取模法是對服務器的數量進行取模,而一致性Hash算法是對2^32取模,什么意思呢?簡單來說,一致性Hash算法將整個哈希值空間組織成一個虛擬的圓環,如假設某哈希函數H的值空間為0-2^32-1(即哈希值是一個32位無符號整形),整個哈希環如下:??

整個空間按順時針方向組織,圓環的正上方的點代表0,0點右側的第一個點代表1,以此類推,2、3、4、5、6……直到2^32-1,也就是說0點左側的第一個點代表2^32-1, 0和2^32-1在零點中方向重合,我們把這個由2^32個點組成的圓環稱為Hash環。

下一步將各個服務器使用Hash進行一個哈希,具體可以選擇服務器的IP或主機名作為關鍵字進行哈希,這樣每臺機器就能確定其在哈希環上的位置,這里假設將上文中四臺服務器使用IP地址哈希后在環空間的位置如下:??

接下來使用如下算法定位數據訪問到相應服務器:將數據key使用相同的函數Hash計算出哈希值,并確定此數據在環上的位置,從此位置沿環順時針“行走”,第一臺遇到的服務器就是其應該定位到的服務器!

例如我們有Object A、Object B、Object C、Object D四個數據對象,經過哈希計算后,在環空間上的位置如下:?

根據一致性Hash算法,數據A會被定為到Node A上,B被定為到Node B上,C被定為到Node C上,D被定為到Node D上。

五、一致性Hash算法的容錯性和可擴展性
現假設Node C不幸宕機,可以看到此時對象A、B、D不會受到影響,只有C對象被重定位到Node D。一般的,在一致性Hash算法中,如果一臺服務器不可用,則受影響的數據僅僅是此服務器到其環空間中前一臺服務器(即沿著逆時針方向行走遇到的第一臺服務器)之間數據,其它不會受到影響,如下所示:

下面考慮另外一種情況,如果在系統中增加一臺服務器Node X,如下圖所示:

此時對象Object A、B、D不受影響,只有對象C需要重定位到新的Node X !一般的,在一致性Hash算法中,如果增加一臺服務器,則受影響的數據僅僅是新服務器到其環空間中前一臺服務器(即沿著逆時針方向行走遇到的第一臺服務器)之間數據,其它數據也不會受到影響。

綜上所述,一致性Hash算法對于節點的增減都只需重定位環空間中的一小部分數據,具有較好的容錯性和可擴展性。

六、Hash環的數據傾斜問題
一致性Hash算法在服務節點太少時,容易因為節點分部不均勻而造成數據傾斜(被緩存的對象大部分集中緩存在某一臺服務器上)問題,例如系統中只有兩臺服務器,其環分布如下:?

此時必然造成大量數據集中到Node A上,而只有極少量會定位到Node B上。為了解決這種數據傾斜問題,一致性Hash算法引入了虛擬節點機制,即對每一個服務節點計算多個哈希,每個計算結果位置都放置一個此服務節點,稱為虛擬節點。具體做法可以在服務器IP或主機名的后面增加編號來實現。

例如上面的情況,可以為每臺服務器計算三個虛擬節點,于是可以分別計算 “Node A#1”、“Node A#2”、“Node A#3”、“Node B#1”、“Node B#2”、“Node B#3”的哈希值,于是形成六個虛擬節點:?

同時數據定位算法不變,只是多了一步虛擬節點到實際節點的映射,例如定位到“Node A#1”、“Node A#2”、“Node A#3”三個虛擬節點的數據均定位到Node A上。這樣就解決了服務節點少時數據傾斜的問題。在實際應用中,通常將虛擬節點數設置為32甚至更大,因此即使很少的服務節點也能做到相對均勻的數據分布。

七、總結
上文中,我們一步步分析了什么是一致性Hash算法,主要是考慮到分布式系統每個節點都有可能失效,并且新的節點很可能動態的增加進來的情況,如何保證當系統的節點數目發生變化的時候,我們的系統仍然能夠對外提供良好的服務,這是值得考慮的!

PHP代碼實現案例:

$hostsMap = ["img1.findme.wang", "img2.findme.wang", "img3.findme.wang"];
$hashRing = [];
 
function getImgSrc($imgName){
    global $hostsMap;
    global $hashRing;
    //將節點映射到hash環上面
    if (empty($hashRing)) {
        foreach($hostsMap as $h) {
            $hostKey = fmod(crc32($h) , pow(2,32));
            $hostKey = abs($hostKey);
            $hashRing[$hostKey] = $h;
        }
        //從小到大排序,便于查找
        ksort($hashRing);
    }
 
    //計算圖片hash
    $imgKey = fmod(crc32($imgName) , pow(2,32));
    $imgKey = abs($imgKey);
    foreach($hashRing as $hostKey => $h) {
        if ($imgKey < $hostKey) {
            return "http://" . $h . "/" . $imgName;
        }
    }
    return "http://" . current($hashRing) . "/" . $imgName;
}
 
var_dump(getImgSrc("logo1.png"));
var_dump(getImgSrc("logo2.png"));
var_dump(getImgSrc("logo3.png"));

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/30931.html

相關文章

  • 致性Hash

    摘要:當時十分興奮,立即去找了關于一致性協議的文章來看。到了今天再去回想,發現對一致性協議的概念已經模糊不清了。一致性算法一致性哈希算法在年由麻省理工學院的等人在解決分布式中提出的,設計目標是為了解決因特網中的熱點問題,初衷和十分類似。 序 第一次知道一致性Hash協議是在方騰飛的技術文章實戰解析-論三年內快速成長為一名技術專家里看到的。 問:對于三十歲的程度員,如果還想再深入做技術,有什么...

    spacewander 評論0 收藏0
  • 通過PHP實現致性哈希算法

    摘要:通過虛擬節點優化一致性算法為了提高一致性算法的平衡性,我們首先能夠想到的是,增加節點數,但是機器畢竟是需要經費啊,不是說增就能隨意增,那就增加虛擬節點,這樣就沒毛病了。 一、案例分析(1)問題概述 假設我們的圖片數據均勻的分配在三臺服務(分別標注為服務器A,服務器B、服務器C)上面,現在我們要從里面取圖片,服務端在拿到這個請求后,怎么會指定,這張圖片是存在服務器A、服務器B,還是服務器...

    tulayang 評論0 收藏0
  • memcached分布式原理與實現

    摘要:哈希的結果應能夠保證原有已分配的內容可以被映射到新的緩沖中去,而不會被映射到舊的緩沖集合中的其他緩沖區。平衡性平衡性是指哈希的結果能夠盡可能分布到所有的緩沖中去,這樣可以使得所有的緩沖空間都得到利用。 memcached分布式原理與實現 標簽(空格分隔): nosql 0x01 概況 1.1 什么是memcached memcached是一個分布式,開源的數據存儲引擎。memcach...

    Ververica 評論0 收藏0
  • memcached分布式原理與實現

    摘要:哈希的結果應能夠保證原有已分配的內容可以被映射到新的緩沖中去,而不會被映射到舊的緩沖集合中的其他緩沖區。平衡性平衡性是指哈希的結果能夠盡可能分布到所有的緩沖中去,這樣可以使得所有的緩沖空間都得到利用。 memcached分布式原理與實現 標簽(空格分隔): nosql 0x01 概況 1.1 什么是memcached memcached是一個分布式,開源的數據存儲引擎。memcach...

    LiuRhoRamen 評論0 收藏0

發表評論

0條評論

feng409

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<