redis主從結(jié)構(gòu) -- 復(fù)制

單機redis不能滿足分區(qū)容錯,當(dāng)主機發(fā)生單點故障的時候矫夷,redis服務(wù)就無法訪問;如果主機的磁盤設(shè)備損壞憋槐,甚至有丟失數(shù)據(jù)的風(fēng)險双藕。可以通過主從結(jié)構(gòu)來避免單點故障的問題秦陋,當(dāng)主機不可用的時候蔓彩,從機仍然保持著數(shù)據(jù)的備份。必要時驳概,可以將從機升級為主機來對外提供服務(wù)赤嚼。

主從結(jié)構(gòu)的需要關(guān)注兩個重要問題分別是:主從數(shù)據(jù)的一致性和主從機器的存活狀態(tài)。本文主要關(guān)注主從數(shù)據(jù)的一致性顺又,即主從復(fù)制更卒。

redis主從結(jié)構(gòu)的建立是通過在從機服務(wù)器執(zhí)行SLAVEOF命令實現(xiàn)的,該命令讓從服務(wù)器連接主服務(wù)器稚照,并去復(fù)制主服務(wù)器的數(shù)據(jù)蹂空。下文皆以master和slave分別指代主俯萌、從服務(wù)器。


slaveof建立主從結(jié)構(gòu)

1.復(fù)制功能的實現(xiàn) (redis2.8以前)

復(fù)制功能包含兩個階段: 同步和命令傳播

  • 同步的作用:將slave的數(shù)據(jù)庫狀態(tài)更新至master的當(dāng)前狀態(tài)
  • 命令傳播的作用: slave更新狀態(tài)更新后上枕,master接收到新的客戶端請求導(dǎo)致master狀態(tài)改變時咐熙,重新使slave更新到與master一致的狀態(tài)。

1.1 同步的過程

  1. slave 向 master 發(fā)送 SYNC 命令
  2. master收到slave的SYNC命令辨萍, 執(zhí)行BGSAVE操作棋恼,在后臺生成數(shù)據(jù)快照RDB文件, 同時使用一個復(fù)制積壓緩沖區(qū)來記錄從生成快照開始锈玉,執(zhí)行的來自于客戶端的寫命令爪飘。
  3. BGSAVE完成,master 將生成的RDB文件發(fā)給slave拉背。slave接收到該文件之后載入文件师崎,更新自己的數(shù)據(jù)庫,使數(shù)據(jù)同步到與 master 在 BGSAVE 開始時相同的狀態(tài)椅棺。
  4. master將緩沖區(qū)內(nèi)的所有寫命令發(fā)送給 slave犁罩, slave執(zhí)行這些命令,更新自己的數(shù)據(jù)庫两疚,讓自己更新至當(dāng)前master所處的狀態(tài)


    image.png

1.2 命令傳播

同步過程完成后昼汗,master收到來自客戶端的寫請求,執(zhí)行后會出現(xiàn)主從狀態(tài)不一致的情況鬼雀。為了使二者一致,master需要將這些命令發(fā)送到slave蛙吏,slave執(zhí)行完這些命令源哩,兩者重新回到一致的狀態(tài)。

1.3 舊版本復(fù)制的缺點

每當(dāng)slave連接master的時候鸦做,都需要完成同步励烦,同步通過BGSAVE生成master中全量數(shù)據(jù)的快照,然后將快照發(fā)送給slave泼诱。這在slave初次連接到master的時候是有必要的坛掠,但是重連情況下,真的有必要全量復(fù)制嗎治筒?
slave與master斷開連接期間屉栓,如果master執(zhí)行的寫入命令很少,為了同步這少量的數(shù)據(jù)耸袜,做全量同步是不劃算的一件事友多。因為BGSAVE需要在后臺耗費大量的CPU、內(nèi)存和磁盤IO資源堤框,同時將全部數(shù)據(jù)發(fā)送給slave需要占用較大的網(wǎng)絡(luò)帶寬和流量域滥,影響master對客戶端請求的響應(yīng)纵柿。
那么能不呢在開銷較小的情況下將這些增量數(shù)據(jù)同步至重連的客戶端呢?有启绰,新版本的復(fù)制支持部分重同步就是做這件事的昂儒。

2.新版本復(fù)制功能

新版本復(fù)制功能是通過PSYNC實現(xiàn)的,它具有完整重同步和部分重同步兩種模式委可。

  • 完整重同步和初次同步SYNC功能相同渊跋,slave發(fā)送命令給master,由master生成RDB文件撤缴,同時在緩沖區(qū)內(nèi)保存寫命令刹枉,將RDB文件和寫命令發(fā)送給slave。主要用于處理初次連接時數(shù)據(jù)同步屈呕。
  • 部分重同步用于處理重連時連接斷開期間master執(zhí)行寫入命令的同步微宝。當(dāng)然,如果產(chǎn)生數(shù)據(jù)量過大虎眨,導(dǎo)致master內(nèi)存不下這么多寫入命令蟋软,那么仍然要通過全量同步。

思考一下為了同步在連接丟失期間內(nèi)master的寫入數(shù)據(jù)嗽桩,我們需要那些信息岳守?

  1. 首先需要一個容器,記錄master的寫入命令碌冶。 對這個容器有以下要求:第一湿痢,不能無限大,否則寫入命令就能把內(nèi)存給占滿了扑庞;第二譬重,既然容量有限,那么應(yīng)當(dāng)優(yōu)先存放最近寫入的命令罐氨⊥喂妫基于這兩個要求,可以使用有限隊列栅隐,由于FIFO的特性塔嬉,當(dāng)隊列滿了之后,將頭部節(jié)點給remove掉租悄,然后在尾部添加新的數(shù)據(jù)谨究。redis由復(fù)制積壓緩沖區(qū)來承擔(dān)該角色。它是一個默認(rèn)大小1MB的FIFO隊列恰矩。
  2. 需要master和slave在恢復(fù)連接時记盒,二者分別執(zhí)行到的最后最后一條命令在隊列中的位置。redis通過復(fù)制偏移量(offset)來完成外傅。
    • master每次向slave發(fā)送N byte的數(shù)據(jù)時纪吮,將自己的offset 加 N
    • slave每次收到master發(fā)送來的N byte數(shù)據(jù)時俩檬,將自己的offset 加 N
  3. slave向master請求重連時,master如何能保證該slave之前就是從自己這里同步的數(shù)據(jù)呢碾盟?顯然需要一個身份憑證棚辽,redis通過運行Id來完成校驗。即slave內(nèi)需要保存master的運行Id冰肴,重連時屈藐,帶上該Id,master校驗這是自己的id熙尉,然后才能向slave發(fā)送增量數(shù)據(jù)联逻,否則將其視為需要全量同步。

2.1 復(fù)制積壓緩沖區(qū)

redis內(nèi)復(fù)制積壓緩沖區(qū)結(jié)構(gòu)如圖:它包含了每個字節(jié)的值和其對應(yīng)的偏移量检痰。


buffer構(gòu)造

2.2服務(wù)器offset

服務(wù)器內(nèi)offset如下圖: master與slave最近一次命令傳播之后包归,雙方offset都在10086. 之后,slave A與master斷開連接铅歼。在連接斷開期間公壤,master收到了新的命令, 之后又向slave傳播了33字節(jié)數(shù)據(jù)椎椰。此時各服務(wù)器的offset狀態(tài)如圖厦幅。


服務(wù)器內(nèi)offset

假設(shè)此時slave A請求重連, 那么他需要向master發(fā)送重連請求慨飘,并帶上自己的offset和內(nèi)部保存的master運行Id确憨。master收到請求后,校驗運行id瓤的,然后從buffer內(nèi)查找slave offset + 1是否在buffer內(nèi)缚态,如果不在,說明這段時間內(nèi)請求較多堤瘤,已經(jīng)將這個數(shù)據(jù)給擠出了緩沖區(qū),那么此時就不能進行部分同步浆熔,因為這樣必然要丟失數(shù)據(jù)本辐。如果在,那么將slave offset + 1 到 master offset的數(shù)據(jù)發(fā)送給slave即可医增。

2.3 PSYNC命令(partial sync)

PSYNC有兩種調(diào)用方式:

  • 如果服務(wù)器執(zhí)行過 SLAVEOF no one 或沒有復(fù)制過任何服務(wù)器, 那么他向master 發(fā)送PSYNC ? -1 命令慎皱,請求master進行完整重同步。
  • 如果該服務(wù)器復(fù)制過某個master叶骨, 則他向master發(fā)送 PSYNC <runid> <offset>命令請求部分重同步茫多, runid為上次連接master的運行ID, offset為slave的當(dāng)前偏移量忽刽。

主服務(wù)器收到PSYNC后天揖,有兩種正常返回值和異常返回:

  • +FULLRESYNC <runid> <offset> (完整重同步)和 +CONTINUE (部分重同步)夺欲。 完整同步的話,slave需要保存runid和offset今膊,在RDB數(shù)據(jù)載入數(shù)據(jù)庫之后需要將自己的初始化偏移量更新為該offset些阅;部分同步則只需要等待master將自己缺失的部分?jǐn)?shù)據(jù)發(fā)送過來,然后將offset + N斑唬。
    如果為-ERR回復(fù)市埋,表示master版本低于Redis2.8,無法識別PSYNC請求


    PSYNC的請求和返回值

同步之后,命令傳播就和舊版本如出一轍了恕刘,在此不作贅述缤谎。

總結(jié)

    1. 主從主要解決的問題: 單點故障容錯,當(dāng)然也可以做讀寫分離褐着,不過似乎沒什么必要坷澡,因為可以做集群,分散每臺master的讀寫壓力献起。
    1. 主從結(jié)構(gòu)如何實現(xiàn)數(shù)據(jù)復(fù)制
    • 舊版本: SYNC + 命令傳播洋访。缺點在于每次重連都需要完整同步,而完整同步需要較大的硬件資源開銷谴餐。
    • 新版本: PSYNC + 命令傳播姻政。重連時通常不希望完整同步,只需要同步在連接斷開期間master的寫入命令即可岂嗓。此時通過復(fù)制緩沖區(qū)和主從雙方的offset即可判斷是否可以從buffer中取出斷開期間的全部寫入命令汁展,可以的話則只需要將buffer中[slave offset + 1 , master offset]區(qū)間內(nèi)的數(shù)據(jù)發(fā)送到slave即可。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末厌殉,一起剝皮案震驚了整個濱河市食绿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌公罕,老刑警劉巖器紧,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異楼眷,居然都是意外死亡铲汪,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門罐柳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來掌腰,“玉大人,你說我怎么就攤上這事张吉〕萘海” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長勺择。 經(jīng)常有香客問我创南,道長,這世上最難降的妖魔是什么酵幕? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任扰藕,我火速辦了婚禮,結(jié)果婚禮上芳撒,老公的妹妹穿的比我還像新娘邓深。我一直安慰自己,他們只是感情好笔刹,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布芥备。 她就那樣靜靜地躺著,像睡著了一般舌菜。 火紅的嫁衣襯著肌膚如雪萌壳。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天日月,我揣著相機與錄音袱瓮,去河邊找鬼。 笑死爱咬,一個胖子當(dāng)著我的面吹牛尺借,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播精拟,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼燎斩,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蜂绎?” 一聲冷哼從身側(cè)響起栅表,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎师枣,沒想到半個月后怪瓶,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡践美,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年劳殖,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拨脉。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖宣增,靈堂內(nèi)的尸體忽然破棺而出玫膀,到底是詐尸還是另有隱情,我是刑警寧澤爹脾,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布帖旨,位于F島的核電站箕昭,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏解阅。R本人自食惡果不足惜落竹,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望货抄。 院中可真熱鬧述召,春花似錦、人聲如沸蟹地。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽怪与。三九已至夺刑,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間分别,已是汗流浹背遍愿。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留耘斩,地道東北人沼填。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像煌往,于是被迫代替她去往敵國和親倾哺。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354

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