1.節(jié)點(diǎn)區(qū)域分區(qū):
使用特定的數(shù)據(jù),如redis的鍵或用戶ID,再根據(jù)節(jié)點(diǎn)數(shù)量N使用公式:hash(key)%N計(jì)算出hash值,用來決定數(shù)據(jù)映射到哪一個(gè)節(jié)點(diǎn)上.
這種方案的問題是:
當(dāng)節(jié)點(diǎn)數(shù)量變化時(shí),需要重新計(jì)算hash,會(huì)導(dǎo)致數(shù)據(jù)的重新遷移.
2.一致性hash算法
一致性hash算法實(shí)現(xiàn)思路是為系統(tǒng)中每一個(gè)節(jié)點(diǎn)分配一個(gè)token,范圍在0~2^32,這些token構(gòu)成一個(gè)hash環(huán).數(shù)據(jù)的讀寫執(zhí)行節(jié)點(diǎn)查找操作時(shí),先根據(jù)key計(jì)算hash值,然后順時(shí)針找到第一個(gè)大于等于該hash的token節(jié)點(diǎn).
好處:
這種方式最大的好處就是,在加入或刪除節(jié)點(diǎn)時(shí),只影響hash環(huán)中相鄰的兩個(gè)節(jié)點(diǎn),對(duì)其他節(jié)點(diǎn)無影響.
問題:
3.虛擬槽算法
使用分散度較好的hash函數(shù),將所有的數(shù)據(jù)映射到 比如0~16383(2^14)范圍的槽中(slot).這個(gè)槽的數(shù)量一般遠(yuǎn)遠(yuǎn)大于實(shí)例的數(shù)量.
槽是集群數(shù)據(jù)管理和遷移的基本單位.采用大范圍槽的主要目的是為了方便數(shù)據(jù)拆分和集群擴(kuò)展.
每一個(gè)實(shí)例會(huì)映射一部分范圍的槽.
特點(diǎn):
1.解耦數(shù)據(jù)和節(jié)點(diǎn)之間的關(guān)系,簡化擴(kuò)容和鎖容的難度
2.節(jié)點(diǎn)自身維護(hù)槽的映射關(guān)系,不需要客戶端或代理服務(wù)維護(hù)槽分區(qū)的元數(shù)據(jù).
3.支持節(jié)點(diǎn),槽,鍵之間的映射查詢,用于數(shù)據(jù)路由,在線伸縮燈場景.
HashTags(面試)
Mset k1 v1 k2 v2 k3 v3
通過分片手段,可以將數(shù)據(jù)合理的劃分到不同的節(jié)點(diǎn)上,這本來是一件好事。但是有的時(shí)候蛀序,我們希望對(duì)相關(guān)聯(lián)的業(yè)務(wù)以原子性方式進(jìn)行操作堪夭。舉個(gè)簡單的例子
我們?cè)趩喂?jié)點(diǎn)上執(zhí)行MSET (m表示多個(gè)饱苟,一次向redis設(shè)置多個(gè)key和值), 它是一個(gè)原子性的操作瓦呼,我們要求所有給定的key要在同一時(shí)間內(nèi)被設(shè)置涨共,不能出現(xiàn)某些指定的key被更新另一些指定的key沒有被更新的情況岖寞。但是在集群環(huán)境下抡四,我們?nèi)匀豢梢詧?zhí)行MSET命令,但它的操作不在是原子操作仗谆,會(huì)存在某些指定的key被更新指巡,而另外一些指定的key沒有改變,原因是多個(gè)key可能會(huì)被分配到不同的機(jī)器上隶垮。
所以藻雪,這里就會(huì)存在一個(gè)矛盾點(diǎn),及要求key盡可能的分散在不同機(jī)器狸吞,又要求某些相關(guān)聯(lián)的key分配到相同機(jī)器勉耀。
這個(gè)也是在面試的時(shí)候會(huì)容易被問到的內(nèi)容。怎么解決呢蹋偏?
從前面的分析中我們了解到便斥,分片其實(shí)就是一個(gè)hash的過程,對(duì)key做hash取模然后劃分到不同的機(jī)器上威始。所以為了解決這個(gè)問題枢纠,我們需要考慮如何讓相關(guān)聯(lián)的key得到的hash值都相同呢?如果key全部相同是不現(xiàn)實(shí)的黎棠,所以怎么解決呢晋渺?在redis中引入了HashTag的概念镰绎,可以使得數(shù)據(jù)分布算法可以根據(jù)key的某一個(gè)部分進(jìn)行計(jì)算,然后讓相關(guān)的key落到同一個(gè)數(shù)據(jù)分片些举;
舉個(gè)簡單的例子跟狱,假如對(duì)于用戶的信息進(jìn)行存儲(chǔ)俭厚,
redis:store:1001户魏、redis:store:1002
那么通過hashtag的方式,
redis:{store}:1001挪挤、redis:{store}:1002; 表示
當(dāng)一個(gè)key包含 {} 的時(shí)候叼丑,就不對(duì)整個(gè)key做hash,而僅對(duì) {} 包括的字符串做hash扛门。