成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

通過PHP實(shí)現(xiàn)一致性哈希算法

tulayang / 2156人閱讀

摘要:通過虛擬節(jié)點(diǎn)優(yōu)化一致性算法為了提高一致性算法的平衡性,我們首先能夠想到的是,增加節(jié)點(diǎn)數(shù),但是機(jī)器畢竟是需要經(jīng)費(fèi)啊,不是說增就能隨意增,那就增加虛擬節(jié)點(diǎn),這樣就沒毛病了。

一、案例分析
(1)問題概述

假設(shè)我們的圖片數(shù)據(jù)均勻的分配在三臺(tái)服務(wù)(分別標(biāo)注為服務(wù)器A,服務(wù)器B、服務(wù)器C)上面,現(xiàn)在我們要從里面取圖片,服務(wù)端在拿到這個(gè)請(qǐng)求后,怎么會(huì)指定,這張圖片是存在服務(wù)器A、服務(wù)器B,還是服務(wù)器C上面呢?若是去遍歷,兩三臺(tái)還好說,但那也太out了,當(dāng)服務(wù)器的數(shù)量達(dá)到成百上千臺(tái)的時(shí)候,還敢說去遍歷嗎?

(2)解決方案

a、通過存儲(chǔ)映射關(guān)系

首先我們可能會(huì)想到,可以搞一個(gè)中間層來記錄圖片存儲(chǔ)在哪個(gè)服務(wù)器上面,如下:

logo1.png =====》 服務(wù)A

ogo2.png =====》 服務(wù)B

logo3.png =====》 服務(wù)C

這樣,每當(dāng)請(qǐng)求過來的時(shí)候,我們先去請(qǐng)求圖片與服務(wù)器的映射關(guān)系,找到圖片存儲(chǔ)的服務(wù)器,在向指定的服務(wù)器發(fā)出請(qǐng)求。從實(shí)現(xiàn)的角度來說,這是可行的,但是在存儲(chǔ)圖片的時(shí)候,我們也必須存儲(chǔ)圖片與服務(wù)器的映射關(guān)系,這明顯加大了工作量,其維護(hù)也是一個(gè)問題,一旦存儲(chǔ)的圖片和服務(wù)器映射關(guān)系出現(xiàn)了問題,整個(gè)系統(tǒng)就掛了。

b、hash算法

既然我們要排除存儲(chǔ)映射關(guān)系,這個(gè)時(shí)候,人們想到了hash算法。如下

圖片在存儲(chǔ)的時(shí)候,依據(jù)圖片名稱(logo1.png),通過hash算法求出散列值val,通過對(duì)val進(jìn)行取模,得出的值,就可以判斷圖片應(yīng)該存儲(chǔ)在哪個(gè)服務(wù)器上面。如下:

key = hash(imgName) % n

其中:

imgName為圖片名稱,

n為服務(wù)器的個(gè)數(shù),

key代表圖片應(yīng)該存儲(chǔ)在第幾個(gè)服務(wù)器上面。

當(dāng)請(qǐng)求過來的時(shí)候,比如請(qǐng)求logo1.png這個(gè)圖片,服務(wù)端依據(jù)上述公式計(jì)算出的key,就可以判斷該logo1.png存儲(chǔ)在哪個(gè)服務(wù)器上面。PHP實(shí)現(xiàn)如下:

$hostsMap = ["img1.findme.wang", "img2.findme.wang", "img3.findme.wang"];
 
function getImgSrc($imgName) {
    global $hostsMap;
    $key = crc32($imgName) % count($hostsMap);
    return "http://" . $hostsMap[abs($key)] . "/" . $imgName;
}
//測(cè)試
var_dump(getImgSrc("logo1.png"));
var_dump(getImgSrc("logo2.png"));
var_dump(getImgSrc("logo3.png"));

輸出:

此時(shí),我們由存儲(chǔ)映射關(guān)系變?yōu)橛?jì)算服務(wù)器的序號(hào),確實(shí)極大的簡(jiǎn)化了工作量。

但是一旦新增機(jī)器,就非常麻煩了,因?yàn)閚變了,幾乎所有的序列號(hào)key也變了,于是需要大量的數(shù)據(jù)遷移工作。

C、一致性hash算法

一致性hash算法,是一種特殊的hash算法,旨在解決當(dāng)node數(shù)(如存儲(chǔ)圖片的服務(wù)器數(shù)量)變化時(shí)候,盡量少數(shù)據(jù)的遷移。

其基本思想:

1、首先把0~2的32次方個(gè)點(diǎn),均勻的分布到一個(gè)圓環(huán)上面,如下:

2、然后將所有的節(jié)點(diǎn)node(存儲(chǔ)圖片的服務(wù)器)通過hash計(jì)算后,對(duì)232取余,然后也映射到hash環(huán)上面,如下:

3、當(dāng)請(qǐng)求過來的時(shí)候,比如請(qǐng)求logo1.png這個(gè)圖片,通過hash計(jì)算后,對(duì)232取余,然后也映射到hash環(huán)上面,如下:

4、然后順時(shí)針轉(zhuǎn)動(dòng),第一個(gè)到達(dá)的節(jié)點(diǎn)node,就認(rèn)為是存儲(chǔ)logo1.png圖片的服務(wù)器。

從上面可以得知,其實(shí)一致性hash的亮點(diǎn),首先在于對(duì)節(jié)點(diǎn)node(存儲(chǔ)圖片的服務(wù)器)和對(duì)象(圖片)都進(jìn)行了hash計(jì)算和映射,其次是閉環(huán)的設(shè)計(jì)。

優(yōu)點(diǎn):當(dāng)新增機(jī)器的時(shí)候,僅僅標(biāo)志出來的區(qū)域受到影響,如下圖:

缺點(diǎn):當(dāng)節(jié)點(diǎn)node比較少的時(shí)候,往往缺少平衡性,因?yàn)榻?jīng)過hash計(jì)算后,映射到hash環(huán)上面的節(jié)點(diǎn)node,并不是均勻分布的,導(dǎo)致了有的機(jī)器負(fù)載很高,有的機(jī)器很空閑。

PHP實(shí)現(xiàn)如下:

$hostsMap = ["img1.findme.wang", "img2.findme.wang", "img3.findme.wang"];
$hashRing = [];
 
function getImgSrc($imgName){
    global $hostsMap;
    global $hashRing;
    //將節(jié)點(diǎn)映射到hash環(huán)上面
    if (empty($hashRing)) {
        foreach($hostsMap as $h) {
            $hostKey = fmod(crc32($h) , pow(2,32));
            $hostKey = abs($hostKey);
            $hashRing[$hostKey] = $h;
        }
        //從小到大排序,便于查找
        ksort($hashRing);
    }
 
    //計(jì)算圖片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"));

輸出結(jié)果如下:

至于為什么使用fmod函數(shù)不適用求余運(yùn)算符%,主要是因?yàn)閜ow(2,32)在32位操作系統(tǒng)上面,超高了PHP_INT_MAX,具體可以參考上一篇文章“PHP中對(duì)大數(shù)求余報(bào)錯(cuò)Uncaught DivisionByZeroError: Modulo by zero”。

d、通過虛擬節(jié)點(diǎn)優(yōu)化一致性hash算法

為了提高一致性hash算法的平衡性,我們首先能夠想到的是,增加節(jié)點(diǎn)數(shù),但是機(jī)器畢竟是需要經(jīng)費(fèi)啊,不是說增就能隨意增,那就增加虛擬節(jié)點(diǎn),這樣就沒毛病了。思路如下:

1、假設(shè)host1、host2、host3,都分別有3個(gè)虛擬節(jié)點(diǎn),如host1的虛擬節(jié)點(diǎn)為host1_1、host1_2、host1_3

2、然后將所有的虛擬節(jié)點(diǎn)node(存儲(chǔ)圖片的服務(wù)器)通過hash計(jì)算后,對(duì)232取余,然后也映射到hash環(huán)上面,如下:

然后,接下來步驟同一致性hash算法一致,只是最后需要將虛擬節(jié)點(diǎn),轉(zhuǎn)為真實(shí)的節(jié)點(diǎn)。

PHP實(shí)現(xiàn)如下:

$hostsMap = ["img1.findme.wang", "img2.findme.wang", "img3.findme.wang"];
$hashRing = [];
 
function getImgSrc($imgName){
    global $hostsMap;
    global $hashRing;
    $virtualNodeLen = 3; //每個(gè)節(jié)點(diǎn)的虛擬節(jié)點(diǎn)個(gè)數(shù)
 
    //將節(jié)點(diǎn)映射到hash環(huán)上面
    if (empty($hashRing)) {
        foreach($hostsMap as $h) {
            $i = 0;
            while($i < $virtualNodeLen){
                $hostKey = fmod(crc32($h."_".$i) , pow(2,32));
                $hostKey = abs($hostKey);
                $hashRing[$hostKey] = $h;
                $i++;
            }
        }
        //從小到大排序,便于查找
        ksort($hashRing);
    }
 
    //計(jì)算圖片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("login1.png"));
var_dump(getImgSrc("login2.png"));
var_dump(getImgSrc("login3.png"));

執(zhí)行結(jié)果如下:

二、備注
1、取模與取余的區(qū)別?

取余,遵循盡可能讓商向0靠近的原則

取模,遵循盡可能讓商向負(fù)無窮靠近的原則

1、什么是CRC算法?

CRC(Cyclical Redundancy Check)即循環(huán)冗余碼校驗(yàn),主要用于數(shù)據(jù)校驗(yàn),常用的有CRC16、CRC32,其中16、32代表多項(xiàng)式最高次冪。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/30928.html

相關(guān)文章

  • [PHP內(nèi)核探索]PHP中的哈希

    摘要:的介紹哈希表是實(shí)現(xiàn)字典操作的一種有效數(shù)據(jù)結(jié)構(gòu)。因此,實(shí)現(xiàn)一個(gè)好的哈希表的關(guān)鍵就是一個(gè)好的哈希函數(shù)和處理哈希沖突的方法。取而代之的是通過應(yīng)用哈希表的,然后只取哈希表的低位。由上面可以看到,的哈希表實(shí)現(xiàn)相當(dāng)復(fù)雜。 在PHP內(nèi)核中,其中一個(gè)很重要的數(shù)據(jù)結(jié)構(gòu)就是HashTable。我們常用的數(shù)組,在內(nèi)核中就是用HashTable來實(shí)現(xiàn)。那么,PHP的HashTable是怎么實(shí)現(xiàn)的呢?最近在看H...

    Yuanf 評(píng)論0 收藏0
  • memcached分布式原理與實(shí)現(xiàn)

    摘要:哈希的結(jié)果應(yīng)能夠保證原有已分配的內(nèi)容可以被映射到新的緩沖中去,而不會(huì)被映射到舊的緩沖集合中的其他緩沖區(qū)。平衡性平衡性是指哈希的結(jié)果能夠盡可能分布到所有的緩沖中去,這樣可以使得所有的緩沖空間都得到利用。 memcached分布式原理與實(shí)現(xiàn) 標(biāo)簽(空格分隔): nosql 0x01 概況 1.1 什么是memcached memcached是一個(gè)分布式,開源的數(shù)據(jù)存儲(chǔ)引擎。memcach...

    Ververica 評(píng)論0 收藏0
  • memcached分布式原理與實(shí)現(xiàn)

    摘要:哈希的結(jié)果應(yīng)能夠保證原有已分配的內(nèi)容可以被映射到新的緩沖中去,而不會(huì)被映射到舊的緩沖集合中的其他緩沖區(qū)。平衡性平衡性是指哈希的結(jié)果能夠盡可能分布到所有的緩沖中去,這樣可以使得所有的緩沖空間都得到利用。 memcached分布式原理與實(shí)現(xiàn) 標(biāo)簽(空格分隔): nosql 0x01 概況 1.1 什么是memcached memcached是一個(gè)分布式,開源的數(shù)據(jù)存儲(chǔ)引擎。memcach...

    LiuRhoRamen 評(píng)論0 收藏0
  • 什么是致性Hash算法?

    摘要:五一致性算法的容錯(cuò)性和可擴(kuò)展性現(xiàn)假設(shè)不幸宕機(jī),可以看到此時(shí)對(duì)象不會(huì)受到影響,只有對(duì)象被重定位到。綜上所述,一致性算法對(duì)于節(jié)點(diǎn)的增減都只需重定位環(huán)空間中的一小部分?jǐn)?shù)據(jù),具有較好的容錯(cuò)性和可擴(kuò)展性。 最近有小伙伴跑過來問什么是Hash一致性算法,說面試的時(shí)候被問到了,因?yàn)椴涣私?,所以就沒有回答上,問我有沒有相應(yīng)的學(xué)習(xí)資料推薦,當(dāng)時(shí)上班,沒時(shí)間回復(fù),晚上回去了就忘了這件事,今天突然看到這個(gè),...

    feng409 評(píng)論0 收藏0
  • 如何對(duì)用戶密碼進(jìn)行加密

    摘要:結(jié)論對(duì)用戶密碼進(jìn)行加密時(shí)需要做到防止用戶密碼明文被竊聽交給,明文傳輸。為什么鹽可以明文存儲(chǔ)攻擊者很難有足夠的計(jì)算資源和存儲(chǔ)空間建立海量的哈希值密碼數(shù)據(jù)庫,針對(duì)單條用戶記錄,建立哈希值密碼數(shù)據(jù)庫進(jìn)行攻擊的成本過高。 摘要 密碼驗(yàn)證是很常見的需求,如何在實(shí)現(xiàn)功能之余,防止用戶密碼泄露,已經(jīng)有了很成熟的方案。這篇文章把自己的思考和結(jié)論做一下記錄。 結(jié)論 對(duì)用戶密碼進(jìn)行加密時(shí)需要做到: 防止用...

    張率功 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<