數(shù)據(jù)分布理論
分布式數(shù)據(jù)庫(kù)首先要解決把整個(gè)數(shù)據(jù)集按照分區(qū)規(guī)則映射到多個(gè)節(jié)點(diǎn)的問(wèn)題,即把數(shù)據(jù)集劃分到多個(gè)節(jié)點(diǎn)上,每個(gè)節(jié)點(diǎn)負(fù)責(zé)整體數(shù)據(jù)的一個(gè)子集。。
需要重點(diǎn)關(guān)注的是數(shù)據(jù)分區(qū)規(guī)則。常見(jiàn)的分區(qū)規(guī)則有哈希分區(qū)和順序分區(qū)兩種,哈希分區(qū)離散度好、數(shù)據(jù)分布業(yè)務(wù)無(wú)關(guān)、無(wú)法順序訪問(wèn),順序分區(qū)離散度易傾斜、數(shù)據(jù)分布業(yè)務(wù)相關(guān)、可順序訪問(wèn)。
節(jié)點(diǎn)取余分區(qū)
使用特定的數(shù)據(jù),如Redis的鍵或用戶ID,再根據(jù)節(jié)點(diǎn)數(shù)量N使用公式hash(key)%N計(jì)算出哈希值,用來(lái)決定數(shù)據(jù)映射到哪一個(gè)節(jié)點(diǎn)上。這種方案存在一個(gè)問(wèn)題:當(dāng)節(jié)點(diǎn)數(shù)量變化時(shí),如擴(kuò)容或收縮節(jié)點(diǎn),數(shù)據(jù)節(jié)點(diǎn)映射關(guān)系需要重新計(jì)算,會(huì)導(dǎo)致數(shù)據(jù)的重新遷移。
這種方式的突出優(yōu)點(diǎn)是簡(jiǎn)單性,常用于數(shù)據(jù)庫(kù)的分庫(kù)分表規(guī)則,一般采用預(yù)分區(qū)的方式,提前根據(jù)數(shù)據(jù)量規(guī)劃好分區(qū)數(shù),比如劃分為512或1024張表,保證可支撐未來(lái)一段時(shí)間的數(shù)據(jù)量再根據(jù)負(fù)載情況將表遷移到其他數(shù)據(jù)庫(kù)中。擴(kuò)容時(shí)通常采用翻倍擴(kuò)容,避免數(shù)據(jù)映射全部被打亂導(dǎo)致全量遷移的情況。
一致性哈希分區(qū)
實(shí)現(xiàn)思路是為系統(tǒng)中每個(gè)節(jié)點(diǎn)分配一個(gè)token,范圍一般在0~23,這些token構(gòu)成一個(gè)哈希環(huán)。數(shù)據(jù)讀寫(xiě)執(zhí)行節(jié)點(diǎn)查找操作時(shí),先根據(jù)key計(jì)算hash值,然后順時(shí)針找到第一個(gè)大于等于該哈希值的token節(jié)點(diǎn)。例如:
集群中有三個(gè)節(jié)點(diǎn)(Node1、Node2、Node3),五個(gè)鍵(key1key2 key3key4、key5),其路由規(guī)為:
?當(dāng)集群中增加節(jié)點(diǎn)時(shí),比如當(dāng)在Node2和Node3之間增加了一個(gè)節(jié)點(diǎn)Node4,此時(shí)再訪問(wèn)節(jié)點(diǎn)key4時(shí),不能在Node4中命中,更一般的,介于Node2和Node4之間的key均失效,這樣的失效方式太過(guò)于“集中”和“暴力”,更好的方式應(yīng)該是“平滑”和“分散”地失效。
?這種方式相比節(jié)點(diǎn)取余最大的好處在于加入和副除節(jié)點(diǎn)只影響哈希環(huán)中相鄰的節(jié)點(diǎn),對(duì)其他節(jié)點(diǎn)無(wú)影響。但一致性哈希分區(qū)存在幾個(gè)問(wèn)題
1、當(dāng)使用少量節(jié)點(diǎn)時(shí),節(jié)點(diǎn)變化將大范圍影響哈希環(huán)中數(shù)據(jù)映射,因此這種方式不適合少量數(shù)據(jù)節(jié)點(diǎn)的分布式方案。
2、增加節(jié)點(diǎn)只能對(duì)下一個(gè)相鄰節(jié)點(diǎn)有比較好的負(fù)載分擔(dān)效果,例如上圖中增加了節(jié)點(diǎn)Node4只能夠?qū)ode3分擔(dān)部分負(fù)載,對(duì)集群中其他的節(jié)點(diǎn)基本沒(méi)有起到負(fù)載分擔(dān)的效果;類似地,刪除節(jié)點(diǎn)會(huì)導(dǎo)致下一個(gè)相鄰節(jié)點(diǎn)負(fù)載增加,而其他節(jié)點(diǎn)卻不能有效分擔(dān)負(fù)載壓力。
正因?yàn)橐恢滦怨7謪^(qū)的這些缺點(diǎn),一些分布式系統(tǒng)采用虛擬槽對(duì)一致性哈希進(jìn)行改進(jìn),比如虛擬一致性哈希分區(qū)。
虛擬一致性哈希分區(qū)
為了在增刪節(jié)點(diǎn)的時(shí)候,各節(jié)點(diǎn)能夠保持動(dòng)態(tài)的均衡,將每個(gè)真實(shí)節(jié)點(diǎn)虛擬出若干個(gè)虛擬節(jié)點(diǎn),再將這些虛擬節(jié)點(diǎn)隨機(jī)映射到環(huán)上。此時(shí)每個(gè)真實(shí)節(jié)點(diǎn)不再映射到環(huán)上,真實(shí)節(jié)點(diǎn)只是用來(lái)存儲(chǔ)鍵值對(duì),它負(fù)責(zé)接應(yīng)各自的一組環(huán)上虛擬節(jié)點(diǎn)。當(dāng)對(duì)鍵值對(duì)進(jìn)行存取路由時(shí),首先路由到虛擬節(jié)點(diǎn)上,再由虛擬節(jié)點(diǎn)找到真實(shí)的節(jié)點(diǎn)。
如下圖所示,三個(gè)節(jié)點(diǎn)真實(shí)節(jié)點(diǎn): Node1、Node2和Node3,每個(gè)真實(shí)節(jié)點(diǎn)虛擬出三個(gè)虛擬節(jié)點(diǎn): X#V1X#V2和X#V3,這樣每個(gè)真實(shí)節(jié)點(diǎn)所負(fù)責(zé)的hash空間不再是連續(xù)的一段,而是分散在環(huán)上的各處,這樣就可以將局部的壓力均衡到不同的節(jié)點(diǎn),虛擬節(jié)點(diǎn)越多,分散性越好,理論上負(fù)載就越傾向均勻。
虛擬槽分區(qū)
Redis則是利用了虛擬槽分區(qū),可以算上面虛擬一致性哈希分區(qū)的變種,它使用分散度良好的哈希函數(shù)把所有數(shù)據(jù)映射到一個(gè)固定范圍的整數(shù)集合中,整數(shù)定義為槽( slot)。這個(gè)范圍一般遠(yuǎn)遠(yuǎn)大于節(jié)點(diǎn)數(shù),比如RedisCluster言范圍是0~16383。槽是集群內(nèi)數(shù)據(jù)管理和遷移的基本單位。采用大范圍槽的主要目的是為了方便數(shù)據(jù)拆分和集群擴(kuò)展。每個(gè)節(jié)點(diǎn)會(huì)負(fù)責(zé)一定數(shù)量的槽
比如集群有3個(gè)節(jié)點(diǎn),則每個(gè)節(jié)點(diǎn)平均大約負(fù)責(zé)5460個(gè)槽。由于采用高質(zhì)量的哈希算法,每個(gè)槽所映射的數(shù)據(jù)通常比較均勻,將數(shù)據(jù)平均劃分到5個(gè)節(jié)點(diǎn)進(jìn)行數(shù)據(jù)分區(qū)。Redis Cluster就是采用虛擬槽分區(qū)下面就介紹Redis數(shù)據(jù)分區(qū)方法。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-544674.html
為什么Redis只取16384個(gè)槽
Redis集群中,在握手成功后,連個(gè)節(jié)點(diǎn)之間會(huì)定期發(fā)送ping/pong消息,交換數(shù)據(jù)信息,集群中節(jié)點(diǎn)數(shù)量越多,消息體內(nèi)容越大,比如說(shuō)10個(gè)節(jié)點(diǎn)的狀態(tài)信息約1kb,同時(shí)redis集群內(nèi)節(jié)點(diǎn),每秒都在發(fā)ping消息,例如個(gè)總節(jié)點(diǎn)數(shù)為200的Redis集群,默認(rèn)情況下,這時(shí)ping/pong消息占用帶寬達(dá)到25M。
那么如果槽位為65536,發(fā)送心跳信息的消息頭達(dá)8k,發(fā)送的心跳包過(guò)于龐大,非常浪費(fèi)帶寬。
其次redis的集群主節(jié)點(diǎn)數(shù)量基本不可能超過(guò)1000個(gè)。集群節(jié)點(diǎn)越多,心跳包的消息體內(nèi)攜帶的數(shù)據(jù)越多。如果節(jié)點(diǎn)過(guò)1000個(gè),也會(huì)導(dǎo)致網(wǎng)絡(luò)擁堵。因此redis作者,不建議redis cluster節(jié)點(diǎn)數(shù)量超過(guò)1000個(gè)。
那么,對(duì)于節(jié)點(diǎn)數(shù)在1000以內(nèi)的redis cluster集群,16384個(gè)槽位夠用了,可以以確保每個(gè) master 有足夠的插槽,沒(méi)有必要拓展到65536個(gè)。
再者Redis主節(jié)點(diǎn)的配置信息中,它所負(fù)責(zé)的哈希槽是通過(guò)一張bitmap的形式來(lái)保存的,在傳輸過(guò)程中,會(huì)對(duì)bitmap進(jìn)行壓縮,但是如果bitmap的填充率slots/N很高的話(N表示節(jié)點(diǎn)數(shù)),也就是節(jié)點(diǎn)數(shù)很少,而哈希槽數(shù)量很多的話,bitmap的壓縮率就很低,也會(huì)浪費(fèi)資源。
所以Redis作者決定取16384個(gè)槽,作為一個(gè)比較好的設(shè)計(jì)權(quán)衡。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-544674.html
到了這里,關(guān)于【緩存中間件】Redis哈希槽的概念的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!