Redis Cluster 分區(qū)實(shí)現(xiàn)原理

Redis Cluster本身提供了自動將數(shù)據(jù)分散到Redis Cluster不同節(jié)點(diǎn)的能力鳞贷,分區(qū)實(shí)現(xiàn)的關(guān)鍵點(diǎn)問題包括:

(1)如何將數(shù)據(jù)自動地打散到不同的節(jié)點(diǎn)蒋川,使得不同節(jié)點(diǎn)的存儲數(shù)據(jù)相對均勻柄瑰?

(2)如何保證客戶端能夠訪問到正確的節(jié)點(diǎn)和數(shù)據(jù)部宿?

(3)如何保證重新分片的過程中不影響正常服務(wù)凶异?

Redis Cluster是由多個(gè)同時(shí)服務(wù)于一個(gè)數(shù)據(jù)集合的Redis實(shí)例組成的整體庶柿,對于用戶來說,用戶只關(guān)注這個(gè)數(shù)據(jù)集合法瑟,而整個(gè)數(shù)據(jù)集合的某個(gè)數(shù)據(jù)子集存儲在哪個(gè)節(jié)點(diǎn)對于用戶來說是透明的冀膝。Redis Cluster具有分布式系統(tǒng)的特點(diǎn),也具有分布式系統(tǒng)如何實(shí)現(xiàn)高可用性與數(shù)據(jù)一致性的難點(diǎn)霎挟,由多個(gè)Redis實(shí)例組成的窝剖。

Redis Cluster特點(diǎn)如下:

(1)所有的節(jié)點(diǎn)相互連接;

(2)集群消息通信通過集群總線通信酥夭,赐纱,集群總線端口大小為客戶端服務(wù)端口+10000,這個(gè)10000是固定值采郎;

(3)節(jié)點(diǎn)與節(jié)點(diǎn)之間通過二進(jìn)制協(xié)議進(jìn)行通信千所;

(4)客戶端和集群節(jié)點(diǎn)之間通信和通常一樣狂魔,通過文本協(xié)議進(jìn)行蒜埋;

(5)集群節(jié)點(diǎn)不會代理查詢

Redis Cluster分區(qū)實(shí)現(xiàn)原理

槽(slot)概念

?Redis Cluster中有一個(gè)16384長度的槽的概念,他們的編號為0最楷、1整份、2、3……16382籽孙、16383烈评。這個(gè)槽是一個(gè)虛擬的槽,并不是真正存在的犯建。正常工作的時(shí)候讲冠,Redis Cluster中的每個(gè)Master節(jié)點(diǎn)都會負(fù)責(zé)一部分的槽,當(dāng)有某個(gè)key被映射到某個(gè)Master負(fù)責(zé)的槽适瓦,那么這個(gè)Master負(fù)責(zé)為這個(gè)key提供服務(wù)竿开,至于哪個(gè)Master節(jié)點(diǎn)負(fù)責(zé)哪個(gè)槽谱仪,這是可以由用戶指定的,也可以在初始化的時(shí)候自動生成(redis-trib.rb腳本)否彩。

這里值得一提的是疯攒,在Redis Cluster中,只有Master才擁有槽的所有權(quán)列荔,如果是某個(gè)Master的slave敬尺,這個(gè)slave只負(fù)責(zé)槽的使用,但是沒有所有權(quán)贴浙。Redis Cluster怎么知道哪些槽是由哪些節(jié)點(diǎn)負(fù)責(zé)的呢砂吞?某個(gè)Master又怎么知道某個(gè)槽自己是不是擁有呢?

位序列結(jié)構(gòu)

Master節(jié)點(diǎn)維護(hù)著一個(gè)16384/8字節(jié)的位序列崎溃,Master節(jié)點(diǎn)用bit來標(biāo)識對于某個(gè)槽自己是否擁有呜舒。比如對于編號為1的槽,Master只要判斷序列的第二位(索引從0開始)是不是為1即可笨奠。?

如上面的序列袭蝗,表示當(dāng)前Master擁有編號為1,134的槽般婆。集群同時(shí)還維護(hù)著槽到集群節(jié)點(diǎn)的映射到腥,是由長度為16384類型為節(jié)點(diǎn)的數(shù)組實(shí)現(xiàn)的,槽編號為數(shù)組的下標(biāo)蔚袍,數(shù)組內(nèi)容為集群節(jié)點(diǎn)乡范,這樣就可以很快地通過槽編號找到負(fù)責(zé)這個(gè)槽的節(jié)點(diǎn)。位序列這個(gè)結(jié)構(gòu)很精巧啤咽,即不浪費(fèi)存儲空間晋辆,操作起來又很便捷。

鍵空間分布基本算法

這里講的是Redis Cluster如何將鍵空間分布在不同的節(jié)點(diǎn)的宇整,鍵空間意為Redis Cluster所擁有用戶所有數(shù)據(jù)集合的鍵的取值范圍瓶佳,這個(gè)范圍叫做鍵空間。提到空間分布鳞青,必然會想到哈希算法霸饲,沒錯(cuò),通過哈希算法再加上取模運(yùn)算可以將一個(gè)值固定地映射到某個(gè)區(qū)間臂拓,在這里厚脉,這個(gè)區(qū)間叫做slots,區(qū)間由連續(xù)的slot組成胶惰。在Redis Cluster中傻工,我們擁有16384個(gè)slot,這個(gè)數(shù)是固定的,我們存儲在Redis Cluster中的所有的鍵都會被映射到這些slot中中捆,下面講講Redis Cluster是如何做映射的威鹿。

鍵到slot的基本映射算法如下:

HASH_SLOT = CRC16(key) mod 16384?

用Redis中的代碼表示如下(這個(gè)代碼被稍微修改了一下,后面會還原):

crc16(key) & 0x3FFF

經(jīng)過簡單的計(jì)算就得到了當(dāng)前key應(yīng)該是存儲在哪個(gè)slot里面轨香,值得注意的是忽你,指定的key會被存儲在哪個(gè)slot,這個(gè)關(guān)系是鐵打不變的臂容。如果我提交了一批命令科雳,往Redis中存儲一批鍵,那么這些鍵一般會被映射到不同的slot脓杉,而不同的slot又可能由Redis Cluster中不同的節(jié)點(diǎn)服務(wù)糟秘,這樣就和的預(yù)期有點(diǎn)不同,有沒有辦法將這批鍵映射到同一個(gè)slot呢球散?答案是可以尿赚。?

鍵哈希標(biāo)簽原理

鍵哈希標(biāo)簽是一種可以讓用戶指定將一批鍵都能夠被存放在同一個(gè)槽中的實(shí)現(xiàn)方法,用戶唯一要做的就是按照既定規(guī)則生成key即可蕉堰,這個(gè)規(guī)則是這樣的凌净,如果我有對于同一個(gè)用戶有兩種不同含義的兩份數(shù)據(jù),我只要將他們的鍵設(shè)置為下面即可:

abc{userId}def和ghi{userId}jkl

redis在計(jì)算槽編號的時(shí)候只會獲取{}之間的字符串進(jìn)行槽編號計(jì)算屋讶,這樣由于上面兩個(gè)不同的鍵冰寻,{}里面的字符串是相同的,因此他們可以被計(jì)算出相同的槽皿渗,相關(guān)代碼如下:

unsigned?int?keyHashSlot(char?*key,?int?keylen)?{

int?s,?e;

for?(s?=?0;?s?<?keylen;?s++)

if?(key[s]?==?'{')?break;


if?(s?==?keylen)?return?crc16(key,keylen)?&?0x3FFF;


for?(e?=?s+1;?e?<?keylen;?e++)

if?(key[e]?==?'}')?break;


if?(e?==?keylen?||?e?==?s+1)?return?crc16(key,keylen)?&?0x3FFF;

return?crc16(key+s+1,e-s-1)?&?0x3FFF;

}

客戶端是怎么在Redis Cluster中找到正確的節(jié)點(diǎn)的呢斩芭?下面看看。

重定向客戶端

文章開始講到乐疆,Redis Cluster并不會代理查詢划乖,那么如果客戶端訪問了一個(gè)key并不存在的節(jié)點(diǎn),這個(gè)節(jié)點(diǎn)是怎么處理的呢挤土?比如我想獲取key為msg的值琴庵,msg計(jì)算出來的槽編號為254,當(dāng)前節(jié)點(diǎn)正好不負(fù)責(zé)編號為254的槽耕挨,那么就會返回客戶端下面信息:

GET?msg

-MOVED?254?127.0.0.1:6381

表示客戶端想要的254槽由運(yùn)行在IP為127.0.0.1细卧,端口為6381的Master實(shí)例服務(wù)尉桩。如果根據(jù)key計(jì)算得出的槽恰好由當(dāng)前節(jié)點(diǎn)負(fù)責(zé)筒占,則當(dāng)期節(jié)點(diǎn)會立即返回結(jié)果。這里明確一下蜘犁,沒有代理的Redis Cluster可能會導(dǎo)致客戶端兩次連接急群中的節(jié)點(diǎn)才能找到正確的服務(wù)翰苫,推薦客戶端緩存連接,這樣最壞的情況是兩次往返通信。

重新分片(Resharding)

重新分片意為槽到集群節(jié)點(diǎn)的映射關(guān)系要改變奏窑,不變的是鍵到槽的映射關(guān)系导披,因此當(dāng)重新分片的時(shí)候,如果槽中有鍵埃唯,那么鍵也是要被移動到新的節(jié)點(diǎn)的撩匕。下面看看重新分片是怎么做的,假如我們有一批槽需要從一個(gè)Master節(jié)點(diǎn)移動到另一個(gè)Master節(jié)點(diǎn):


這里簡化模型墨叛,假設(shè)這批待遷移的槽編號為1止毕、2、3漠趁,并假設(shè)左邊的節(jié)點(diǎn)為MasterA節(jié)點(diǎn)扁凛,右邊的節(jié)點(diǎn)為MasterB節(jié)點(diǎn)。

槽遷移的過程

槽遷移的過程中有一個(gè)不穩(wěn)定狀態(tài)闯传,這個(gè)不穩(wěn)定狀態(tài)會有一些規(guī)則谨朝,這些規(guī)則定義客戶端的行為,從而使得Redis Cluster不必宕機(jī)的情況下可以執(zhí)行槽的遷移甥绿。下面這張圖描述了我們遷移編號為1字币、2、3的槽的過程中共缕,他們在MasterA節(jié)點(diǎn)和Master節(jié)點(diǎn)中的狀態(tài)纬朝。

MIGRATING狀態(tài)?

本例中MIGRATING狀態(tài)是發(fā)生在MasterA節(jié)點(diǎn)中的一種槽的狀態(tài),預(yù)備遷移槽的時(shí)候槽的狀態(tài)首先會變?yōu)镸IGRATING狀態(tài)骄呼,這種狀態(tài)的槽會實(shí)際產(chǎn)生什么影響呢?當(dāng)客戶端請求的某個(gè)Key所屬的槽處于MIGRATING狀態(tài)的時(shí)候共苛,影響有下面幾條:

如果Key存在則成功處理?

如果Key不存在,則返回客戶端ASK蜓萄,僅當(dāng)這次請求會轉(zhuǎn)向另一個(gè)節(jié)點(diǎn)隅茎,并不會刷新客戶端中node的映射關(guān)系,也就是說下次該客戶端請求該Key的時(shí)候嫉沽,還會選擇MasterA節(jié)點(diǎn)?

如果Key包含多個(gè)命令辟犀,如果都存在則成功處理,如果都不存在绸硕,則返回客戶端ASK堂竟,如果一部分存在,則返回客戶端TRYAGAIN玻佩,通知客戶端稍后重試出嘹,這樣當(dāng)所有的Key都遷移完畢的時(shí)候客戶端重試請求的時(shí)候回得到ASK,然后經(jīng)過一次重定向就可以獲取這批鍵

IMPORTING狀態(tài)

本例中的IMPORTING狀態(tài)是發(fā)生在MasterB節(jié)點(diǎn)中的一種槽的狀態(tài)咬崔,預(yù)備將槽從MasterA節(jié)點(diǎn)遷移到MasterB節(jié)點(diǎn)的時(shí)候税稼,槽的狀態(tài)會首先變?yōu)镮MPORTING烦秩。IMPORTING狀態(tài)的槽對客戶端的行為有下面一些影響:

正常命令會被MOVED重定向,如果是ASKING命令則命令會被執(zhí)行郎仆,從而Key沒有在老的節(jié)點(diǎn)已經(jīng)被遷移到新的節(jié)點(diǎn)的情況可以被順利處理只祠;?

如果Key不存在則新建;?

沒有ASKING的請求和正常請求一樣被MOVED扰肌,這保證客戶端node映射關(guān)系出錯(cuò)的情況下不會發(fā)生寫錯(cuò)抛寝;?

鍵空間遷移

鍵空間遷移是指當(dāng)滿足了槽遷移前提的情況下,我們就可以通過相關(guān)命令將槽1曙旭、2墩剖、3中的鍵空間從MasterA節(jié)點(diǎn)轉(zhuǎn)移到MasterB節(jié)點(diǎn),這個(gè)過程真正實(shí)現(xiàn)數(shù)據(jù)轉(zhuǎn)移夷狰。相關(guān)命令:?

MIGRATE

DUMP

RESTORE

DEL

MIGRATE命令通過三步將數(shù)據(jù)轉(zhuǎn)移岭皂,示意圖如下:


經(jīng)過上面三步可以將鍵空間數(shù)據(jù)遷移,然后再將處于MIGRATING和IMPORTING狀態(tài)的槽變?yōu)槌B(tài)即可沼头,完成整個(gè)重新分片的過程爷绘。然而MIGRATE并不是原子的,如果在MIGRATE出現(xiàn)錯(cuò)誤的情況可能會導(dǎo)致下面問題:

(1)鍵空間在兩個(gè)節(jié)點(diǎn)都存在进倍;

(2)鍵空間只存在第一個(gè)節(jié)點(diǎn)土至;


詳情查看

http://www.cnblogs.com/wxd0108/p/5729754.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市猾昆,隨后出現(xiàn)的幾起案子陶因,更是在濱河造成了極大的恐慌,老刑警劉巖垂蜗,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件楷扬,死亡現(xiàn)場離奇詭異,居然都是意外死亡贴见,警方通過查閱死者的電腦和手機(jī)烘苹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來片部,“玉大人镣衡,你說我怎么就攤上這事〉涤疲” “怎么了廊鸥?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長辖所。 經(jīng)常有香客問我惰说,道長,這世上最難降的妖魔是什么奴烙? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任助被,我火速辦了婚禮剖张,結(jié)果婚禮上切诀,老公的妹妹穿的比我還像新娘揩环。我一直安慰自己,他們只是感情好幅虑,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布丰滑。 她就那樣靜靜地躺著,像睡著了一般倒庵。 火紅的嫁衣襯著肌膚如雪褒墨。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天擎宝,我揣著相機(jī)與錄音郁妈,去河邊找鬼。 笑死绍申,一個(gè)胖子當(dāng)著我的面吹牛噩咪,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播极阅,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼胃碾,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了筋搏?” 一聲冷哼從身側(cè)響起仆百,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎奔脐,沒想到半個(gè)月后俄周,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡髓迎,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年栈源,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片竖般。...
    茶點(diǎn)故事閱讀 40,090評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡甚垦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出涣雕,到底是詐尸還是另有隱情艰亮,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布挣郭,位于F島的核電站迄埃,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏兑障。R本人自食惡果不足惜侄非,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一蕉汪、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧逞怨,春花似錦者疤、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至除秀,卻和暖如春糯累,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背册踩。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工泳姐, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人暂吉。 一個(gè)月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓胖秒,卻偏偏與公主長得像,于是被迫代替她去往敵國和親借笙。 傳聞我的和親對象是個(gè)殘疾皇子扒怖,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)發(fā):Redis Cluster探索與思考 Redis Cluster的基本原理和架構(gòu) Redis Cluster...
    meng_philip123閱讀 3,587評論 0 14
  • Redis集群 Redis數(shù)據(jù)分區(qū) 思考: 主從復(fù)制是通過將master上的數(shù)據(jù)全量的復(fù)制到一個(gè)或多個(gè)節(jié)點(diǎn)上,這是...
    javap閱讀 1,407評論 0 6
  • 前面我們介紹了國人自己開發(fā)的Redis集群方案——Codis业稼,Codis友好的管理界面以及強(qiáng)大的自動平衡槽位的功能...
    Jackeyzhe閱讀 2,073評論 0 3
  • NOSQL類型簡介鍵值對:會使用到一個(gè)哈希表盗痒,表中有一個(gè)特定的鍵和一個(gè)指針指向特定的數(shù)據(jù),如redis低散,volde...
    MicoCube閱讀 3,982評論 2 27
  • Redis Cluster原理分析 文章較長俯邓,如需轉(zhuǎn)載可分段。轉(zhuǎn)載請標(biāo)明作者以及文章來源熔号,謝謝稽鞭! 作者介紹 姓名:...
    lihanglucien閱讀 20,464評論 3 30