Tim Yang去年在博客(http://)討論一個(gè)有狀態(tài)服務(wù)的場(chǎng)景下如何使用一致性哈希算法的問(wèn)題,。其中主要涉及到增加或刪除節(jié)點(diǎn)時(shí)引起的系統(tǒng)震蕩。其中也討論了是否使用隨機(jī)選取節(jié)點(diǎn),,并使用memcached保持選擇的方案,。
我們知道一致性哈希算法可以很好的解決增加或刪除節(jié)點(diǎn)時(shí)引起的系統(tǒng)震蕩問(wèn)題。采用虛擬節(jié)點(diǎn)后,,平均的將增刪節(jié)點(diǎn)產(chǎn)生的震蕩分配到其他節(jié)點(diǎn)上,。測(cè)試證實(shí)了一致性哈希算法有很良好的平均性。 我們做一個(gè)簡(jiǎn)單測(cè)試: 有50個(gè)node,,200個(gè)虛節(jié)點(diǎn),,100000個(gè)session。分別測(cè)試增加10%的節(jié)點(diǎn)和刪除10%的節(jié)點(diǎn)對(duì)系統(tǒng)有多少影響,。結(jié)果分析如下,, Normal case : nodes count : 50 Added case : nodes count : 55 Reduced case : nodes count : 45 85512 --- 85431 Same percent in added case : 89.218124% Same percent in reduced case : 89.13361% (增加或刪除10%的節(jié)點(diǎn)后,仍有約89%的session被分配給原有節(jié)點(diǎn)) 但測(cè)試中暴露了兩個(gè)問(wèn)題,,有待以后研究,。 一個(gè)是隨著節(jié)點(diǎn)數(shù)的增加,分配給每個(gè)節(jié)點(diǎn)的session不再是非常平均,。特別是在環(huán)開始的幾個(gè)節(jié)點(diǎn)分配的較少 第二是當(dāng)節(jié)點(diǎn)數(shù)量很多時(shí),,比如2^32大小的尋址空間上,如果節(jié)點(diǎn)數(shù)量很大,超過(guò)1000個(gè)虛節(jié)點(diǎn),,算法性能就開始有比較明顯的下降,。這可能是由于實(shí)現(xiàn)問(wèn)題,但是還需要調(diào)研,。 回到原來(lái)的問(wèn)題上,,即什么樣的場(chǎng)景適合使用一致性哈希算法。 這里有兩類場(chǎng)景,,我們先來(lái)討論比較簡(jiǎn)單的情況,。 場(chǎng)景一 假設(shè)有一種靜態(tài)資源,例如視頻,、網(wǎng)頁(yè),、大型log文件等,只有第一次請(qǐng)求時(shí)才加載到系統(tǒng)中,。我們希望以后每次對(duì)相關(guān)資源的請(qǐng)求都送達(dá)到同一個(gè)節(jié)點(diǎn),。這樣可以最大限度的利用整個(gè)集群的能力,這也是CDN的基本思路,。 這類場(chǎng)景的特點(diǎn)是, 1,,在高并發(fā)情況下,,如何使多個(gè)并發(fā)請(qǐng)求都被發(fā)送到同一節(jié)點(diǎn)。 2,,session實(shí)際是無(wú)狀態(tài)的 在該情況下,,使用一致性哈希是很合適的。我在構(gòu)建高性能Java服務(wù)器中談到了使用一致性哈希算法替代多線程上同步鎖,,從而極大的提高系統(tǒng)性能,。就是在這個(gè)場(chǎng)景下實(shí)現(xiàn)的。 場(chǎng)景二 一個(gè)有狀態(tài)服務(wù),,持有大量有狀態(tài)session,,且session不斷的被更新和查詢。 這種類型的session是不可能被實(shí)時(shí)更新到數(shù)據(jù)庫(kù)的,,因此它們只能在分布式內(nèi)存中被保持,。由于session更新頻繁,且要特別考慮到場(chǎng)景是多線程同時(shí)受理對(duì)同一session的多個(gè)請(qǐng)求,。因此我們的考慮是,,不能完全把session保存在一個(gè)分布式memory中,因?yàn)轭l繁的更新對(duì)CPU和網(wǎng)絡(luò)都有比較大的壓力session異步備份,,還是那句話,,這次業(yè)務(wù)可以失敗,但是系統(tǒng)不能因?yàn)闃I(yè)務(wù)無(wú)法更新而停止工作 可以有幾種解決方案,, buddy replication+一致性哈希 借鑒Jboss Cache buddy replication的思路,。為了減少網(wǎng)絡(luò)和被備份節(jié)點(diǎn)的壓力,,我們不希望把session復(fù)制到整個(gè)cluster上。但是又希望可以當(dāng)單點(diǎn)crash后從內(nèi)存恢復(fù)數(shù)據(jù),。因此我們只把session備份到幾個(gè)節(jié)點(diǎn)上,,例如當(dāng)一致性哈希找到了工作節(jié)點(diǎn)后,該工作節(jié)點(diǎn)再使用固定后綴找到buddy node進(jìn)行復(fù)制,。 例如,,sessionID+"buddy1";sessionID+"buddy2",; 每次更新本地session的同時(shí),,節(jié)點(diǎn)異步的向buddy中的memcached寫一個(gè)備份。如果本節(jié)點(diǎn)crash,,session被分配到其他節(jié)點(diǎn)處理,,它會(huì)試圖從buddy的memcached中取回狀態(tài)。 whole cluster replication 如果你的服務(wù)要求一個(gè)會(huì)話都不能丟失,,則只能進(jìn)行全cluster復(fù)制,。這樣可以保證任何一節(jié)點(diǎn)活著就能繼續(xù)進(jìn)行業(yè)務(wù)。我們測(cè)試過(guò)一些開源產(chǎn)品,,比如Jboss InfiniSpan,, 在節(jié)點(diǎn)數(shù)量不大,且網(wǎng)絡(luò)條件很好的情況,,僅用UDP進(jìn)行whole cluster replication效果就很好,。如果參考其實(shí)可以發(fā)現(xiàn),通過(guò)NIO/TCP進(jìn)行可序列號(hào)對(duì)象復(fù)制,,其速度和可靠性在節(jié)點(diǎn)數(shù)較多的集群中也可以工作的很好,。 以上兩種場(chǎng)景在實(shí)際運(yùn)營(yíng)的系統(tǒng)中都可勝任,當(dāng)然對(duì)于不同客戶的不同要求,,需要采用不同的架構(gòu),。另外要考慮到團(tuán)隊(duì)的能力,比如團(tuán)隊(duì)如果一直基于JBoss開發(fā),,且用戶對(duì)session狀態(tài)的丟失率有嚴(yán)格要求,,則采用Jboss Cache是最簡(jiǎn)單的方法。盡管它顯然沒(méi)有一致性哈希這么酷:) 本文純屬原創(chuàng),,歡迎轉(zhuǎn)載,,請(qǐng)注明原網(wǎng)址; |
|