最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java一致性Hash算法的實現(xiàn)詳解

 更新時間:2024年01月26日 09:45:22   作者:ZhaoJuFei  
這篇文章主要介紹了Java一致性Hash算法的實現(xiàn)詳解,hash的意思是散列,目的將一組輸入的數(shù)據(jù)均勻的分開、打散,往往用來配合路由算法做負載均衡,多用在分布式系統(tǒng)中,需要的朋友可以參考下

 哈希hash

hash的意思是散列,目的將一組輸入的數(shù)據(jù)均勻的分開、打散,往往用來配合路由算法做負載均衡,多用在分布式系統(tǒng)中。

比如memcached它只提供了K V的存儲、讀取,如果使用了多臺memcache做一個“邏輯集群”,就需要客戶端做“路由算法”,來保證數(shù)據(jù)均勻的進去,然后能“原路”拿出來。

常規(guī)哈希取模

常規(guī)哈希,往往結(jié)合取模運算,以便將請求轉(zhuǎn)發(fā)到后端的服務(wù)器上,如下圖:

第一步使用hash算法,將請求“打散”得到一個整數(shù)(比如傳遞過來一個請求,使用jdk類庫的hash對某個參數(shù)做計算),第二步將得到的參數(shù)對后端的服務(wù)器臺數(shù)取模,以上圖為例,加上有三臺服務(wù)器,那么id分別為1~6的請求會被轉(zhuǎn)發(fā)到1,2,0,1,2,0,上,不管請求id數(shù)是多少,總是這么周而復(fù)始的轉(zhuǎn)發(fā)。

假設(shè)上面是個緩存系統(tǒng),以上請求為set請求,在服務(wù)器數(shù)量不變的情況下,對同樣的id做get請求,由于采用同樣的hash算法,那么肯定能原路找到對應(yīng)的key值。這個算法簡單,而且數(shù)據(jù)分散的均勻。

如果系統(tǒng)訪問量突增,為了擴容加了一臺機器,編號為3,此時有了4臺機器,采用同樣的算法再去get請求會如何?比如id=6,這個時候 6%4=2,我們知道set時值其實放進了索引為0的機器,這個時候就get不到了。這就是上面算法的弊端,在增減機器時會使舊的數(shù)據(jù)大量“失效”,也就是命中率下降。

不帶虛擬節(jié)點的一致性哈希算法

為了解決以上問題,聰明的人發(fā)明了一致性哈希算法。思路是這樣,hash算法出來的整數(shù)有個范圍,我們在這個范圍內(nèi)布置三臺服務(wù)器(范圍具體是多少看前面的hash算法)。假設(shè)hash的范圍是1~300,每臺負責一段范圍內(nèi)的請求,比如一臺負責(1~100],一臺負責(100~200],一臺負責(200~1]。這三臺server收尾相接覆蓋/閉環(huán)了所有請求,稱為哈希環(huán),如下圖:

如何實現(xiàn)一臺服務(wù)器接收一個范圍的請求?這個時候不用取模了,而是將server也按照hash算法計算一個id值,比如按照他們的ip+port+name拼成的串計算,假設(shè)正好分別是 1,100,200,將他們放進一個treeMap里,Map<Inetger,Node> ,其中Node代表server節(jié)點,是自定義的數(shù)據(jù)結(jié)構(gòu),比如是一個類,包含ip,port,name等屬性。我們的例子中,map里包含三個元素。

一個請求過來hash得到的值必屬于這三個server的范圍,比如一個請求id=N,那么從map里get(N)去找server,找到直接轉(zhuǎn)發(fā),找不到進行如下運算:treemap里有個關(guān)鍵的api,tailMap(),這個接口能夠返回id比N大的map的子集,然后取子集的第一個節(jié)點,就是id=100的節(jié)點,通常稱為順時針查找。

//得到應(yīng)當路由到的結(jié)點(示例代碼用String代表的節(jié)點)
private static String getServer(String key) {
	//得到該key的hash值
	int hash = getHash(key);
	//得到大于該Hash值的所有Map
	SortedMap<Integer, String> subMap = sortedMap.tailMap(hash);
	if(subMap.isEmpty()){
		//如果沒有比該key的hash值大的,則從第一個node開始
		Integer i = sortedMap.firstKey();
		//返回對應(yīng)的服務(wù)器
		return sortedMap.get(i);
	}else{
		//第一個Key就是順時針過去離node最近的那個結(jié)點
		Integer i = subMap.firstKey();
		//返回對應(yīng)的服務(wù)器
		return subMap.get(i);
	}
}

當然如果子集為空,這意味著N>200,就取整個map的第一個節(jié)點,完成閉環(huán)。

分析:從實現(xiàn)可以看出,如果一個節(jié)點掛了,他的流量會順時針(逆時針實現(xiàn)也是一樣的)“導(dǎo)流”到下一個節(jié)點,其他節(jié)點不受影響。假如有100臺服務(wù)器,一臺掛了,其他99臺都能正常命中!這個算法比簡單的取模好了很多。

不過這里仍有個問題,假設(shè)各臺服務(wù)器性能差不多,此時流量突增,一臺server由于流量過載而掛掉,那么它的下一臺因為承載了2倍的流量,很有可能也會掛掉,依此類推,最后所有的節(jié)點都會掛掉,造成“雪崩”!

因此正常情況下,我們往往采用帶虛擬節(jié)點的一致性哈希算法(不特別說明的一致性哈希算法一般都是指的帶虛擬節(jié)點的算法)。

帶虛擬節(jié)點的一致性哈希算法

帶虛擬節(jié)點的一致性哈希算法是為了解決不帶虛擬節(jié)點算法的雪崩問題,虛擬節(jié)點也稱為分片。在上一步的基礎(chǔ)上理解虛擬節(jié)點是非常容易的。“虛擬”節(jié)點是server的副本、分身,每個虛擬節(jié)點存儲的server信息還是后面的物理地址,只不過每個server由一臺變成了多臺,這個時候往treeMap放節(jié)點時往往這么做:

for(i=1  -->  N) // N為每個server對應(yīng)的分片數(shù)量
{
   Map.put(hash(ip+port+name+i),node) // 所有虛擬節(jié)點放進去
}
這個for循環(huán)外面還會有個循環(huán),處理所有server node

由于每個server的ip,name不同,所以以上拼串hash后的值碰撞的概率是很小的,這樣所有的虛擬節(jié)點也會離散的分部到環(huán)上,形成的hash環(huán)如下圖,同樣顏色的虛擬節(jié)點同屬于一個server。

這個時候如果紅顏色的server掛了,它的虛擬節(jié)點負責的范圍會分別導(dǎo)航到下一個虛擬節(jié)點上,這些虛擬節(jié)點分別屬于不同的server,就避免了流量全部導(dǎo)流到一臺機器上。由于流量被均攤了,有效的減少了雪崩發(fā)生的概率。(理論上仍存在虛擬節(jié)點后面的虛擬節(jié)點屬于同一個server的情況,但是當虛擬節(jié)點非常多時,這個概率是非常小的,而且這個分片數(shù)量是自定義的,往往設(shè)置幾百個)。

只要是hash算法,就有哈希碰撞的可能性,在增加server時,計算后的虛擬節(jié)點跟其他server的虛擬節(jié)點重復(fù)的話,也會導(dǎo)致部分緩存失效(可以通過算法改良)。

綜上,一致性哈希算法并不是強一致性,也不是高可用方案,如果server掛了數(shù)據(jù)丟了就是丟了,除非有恢復(fù)手段,它只是一種減少由擴縮容引起的命中率下降的手段。

到此這篇關(guān)于Java一致性Hash算法的實現(xiàn)詳解的文章就介紹到這了,更多相關(guān)Java一致性Hash算法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java8中List轉(zhuǎn)Map的多種方式代碼

    Java8中List轉(zhuǎn)Map的多種方式代碼

    這篇文章主要給大家介紹了關(guān)于Java8中List轉(zhuǎn)Map的多種方式,在實際項目中我們經(jīng)常會用到List轉(zhuǎn)Map操作,本文介紹了多種方法的實現(xiàn)代碼,需要的朋友可以參考下
    2023-08-08
  • 一文詳解Java如何使用commons-csv搞定CSV文件操作

    一文詳解Java如何使用commons-csv搞定CSV文件操作

    在?Java?開發(fā)中,處理?CSV(逗號分隔值)文件是一項常見的任務(wù),本文將利用Apache?Commons?CSV?庫實現(xiàn)讀取,寫入和操作CSV文件,希望對大家有所幫助
    2025-02-02
  • Mybatis實現(xiàn)查詢相冊數(shù)據(jù)列表流程講解

    Mybatis實現(xiàn)查詢相冊數(shù)據(jù)列表流程講解

    這篇文章主要介紹了Mybatis實現(xiàn)查詢相冊數(shù)據(jù)列表流程,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧
    2022-12-12
  • 在JAR文件中找不到主清單屬性的原因與解決方案

    在JAR文件中找不到主清單屬性的原因與解決方案

    在Java中,一個JAR文件通常包含一個名為MANIFEST.MF的清單文件,這個文件定義了關(guān)于JAR文件的各種元數(shù)據(jù),然而,有時我們可能會遇到一個問題,那就是在JAR文件中找不到主清單屬性,本文給大家介紹了JAR文件中找不到主清單屬性的原因和解決方案,需要的朋友可以參考下
    2024-04-04
  • springboot @WebFilter注解過濾器的實現(xiàn)

    springboot @WebFilter注解過濾器的實現(xiàn)

    這篇文章主要介紹了springboot @WebFilter注解過濾器的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-03-03
  • Java數(shù)組擴容的三大小結(jié)

    Java數(shù)組擴容的三大小結(jié)

    當數(shù)組需要容納更多元素時,可以通過擴容來增加其容量,本文主要介紹了Java數(shù)組擴容的三大小結(jié),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-08-08
  • 了解JAVA Future類

    了解JAVA Future類

    Future是并發(fā)編程中的一種設(shè)計模式,F(xiàn)uture它代表一個異步計算的結(jié)果,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,下面小編和大家來一起學習一下吧
    2019-06-06
  • Spring Data JPA調(diào)用存儲過程實例代碼

    Spring Data JPA調(diào)用存儲過程實例代碼

    本篇文章主要介紹了Spring Data JPA調(diào)用存儲過程實例代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2017-04-04
  • Java使用sftp定時下載文件的示例代碼

    Java使用sftp定時下載文件的示例代碼

    SFTP 為 SSH的其中一部分,是一種傳輸檔案至 Blogger 伺服器的安全方式。接下來通過本文給大家介紹了Java使用sftp定時下載文件的示例代碼,感興趣的朋友跟隨腳本之家小編一起看看吧
    2018-05-05
  • 談?wù)凥ashmap的容量為什么是2的冪次問題

    談?wù)凥ashmap的容量為什么是2的冪次問題

    這篇文章主要介紹了談?wù)凥ashmap的容量為什么是2的冪次問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09

最新評論

玉山县| 桃园市| 东乌珠穆沁旗| 德兴市| 航空| 长岛县| 张掖市| 卓尼县| 达州市| 耿马| 阳信县| 富源县| 自治县| 新疆| 花莲县| 灵武市| 南江县| 寻甸| 荆州市| 寻乌县| 藁城市| 从江县| 大余县| 房山区| 博白县| 大化| 栾城县| 巢湖市| 南澳县| 五寨县| 洛川县| 阜平县| 平乡县| 巴楚县| 万山特区| 湄潭县| 大足县| 潞西市| 大悟县| 夏邑县| 电白县|