研發(fā)工作中我們總是會用到緩存坎拐,redis作為目前互聯(lián)網(wǎng)企業(yè)最流行的緩存中間件担忧,我們這篇文章想跟大家一起討論下它的集群解決方案芹缔。
后續(xù)筆者會從redis的主從同步機(jī)制、哨兵模式(Sentinel)瓶盛、Codis最欠、Cluster幾個方向來逐一闡述自己的觀點(diǎn)。
這篇文章主要討論redis的主從同步機(jī)制惩猫。很多公司未必會有redis集群芝硬,但是使用redis的時候至少都做了主從來保證服務(wù)的可用性。
什么是主從轧房?顧名思義拌阴,一個節(jié)點(diǎn)作為Master,一個節(jié)點(diǎn)作為Slave奶镶,當(dāng)Master作為掛掉的時候迟赃,Slave過來接管,服務(wù)就可以繼續(xù)实辑,否則Master的重啟捺氢、數(shù)據(jù)恢復(fù)過程可能會拖延很長時間,從而影響到業(yè)務(wù)系統(tǒng)的持續(xù)服務(wù)剪撬。
說道集群摄乒,我們就會想到著名的CAP原理。
C:Consistent残黑,一致性
A:Availability馍佑,可用性
P:Partition tolerance,分區(qū)一致性
這里有個術(shù)語需要解釋:網(wǎng)絡(luò)分區(qū)梨水。分布式系統(tǒng)的節(jié)點(diǎn)通常都是分布在不同的機(jī)器上拭荤,機(jī)器之間的網(wǎng)絡(luò)有可能會斷開,當(dāng)網(wǎng)絡(luò)斷開時疫诽,這樣的場景就叫做網(wǎng)絡(luò)分區(qū)舅世。
網(wǎng)絡(luò)分區(qū)發(fā)生時,由于節(jié)點(diǎn)間無法通信奇徒,如果持續(xù)寫入或者修改數(shù)據(jù)雏亚,會導(dǎo)致節(jié)點(diǎn)之間數(shù)據(jù)一致性無法保證。除非當(dāng)分區(qū)發(fā)生時摩钙,我們不在提供服務(wù)罢低,直到網(wǎng)絡(luò)恢復(fù),這樣就犧牲了可用性胖笛。所以CAP的原理是:當(dāng)網(wǎng)絡(luò)分區(qū)發(fā)生時网持,C與A難以兩全宜岛。
redis的主從數(shù)據(jù)是異步同步的,所以分布式的redis只能滿足AP功舀。當(dāng)客戶端在redis的主節(jié)點(diǎn)修改了數(shù)據(jù)后萍倡,立即返回。所以主從的網(wǎng)絡(luò)分區(qū)發(fā)生時日杈,主節(jié)點(diǎn)會繼續(xù)提供服務(wù)遣铝,從節(jié)點(diǎn)的數(shù)據(jù)版本會在網(wǎng)絡(luò)恢復(fù)后,通過多種策略進(jìn)行恢復(fù)莉擒,盡力保持與主節(jié)點(diǎn)一致酿炸。達(dá)成最終一致性。
redis支持主從同步與從從同步涨冀。如下圖:
下面我們再談一下主從同步的幾種策略:
1.增量同步
redis同步的是指令流填硕,主節(jié)點(diǎn)會將對自己的狀態(tài)產(chǎn)生修改性影響的指令記錄在本地的內(nèi)存buffer中,然后異步將buffer中的指令同步到從節(jié)點(diǎn)鹿鳖,從節(jié)點(diǎn)一邊執(zhí)行同步的指令流扁眯,一邊向主節(jié)點(diǎn)反饋同步偏移量。
由于buffer的大小有限翅帜,所以是循環(huán)使用的姻檀。如果因?yàn)榫W(wǎng)絡(luò)故障,導(dǎo)致master與slave之間的數(shù)據(jù)不一致涝滴,同時buffer里面的數(shù)據(jù)版本已經(jīng)被覆蓋了绣版,那么redis會觸發(fā)快照同步。
2.快照同步
快照同步因?yàn)樯婕暗酱疟PIO歼疮,所以是一種非常耗費(fèi)資源的操作杂抽。
master通過bgsave操作將內(nèi)存快照存儲到磁盤文件,然后將快照文件發(fā)送到從節(jié)點(diǎn)韩脏,從節(jié)點(diǎn)接收完畢后缩麸,立即執(zhí)行一次全量加載。全量加載操作前需要清空內(nèi)存赡矢,加載完畢后通知master繼續(xù)進(jìn)行增量同步杭朱。
問題:加載快照時間過長或者復(fù)制buffer太小都會導(dǎo)致同步期間的增量指令在復(fù)制buffer中被覆蓋,導(dǎo)致快照同步完成后無法增量復(fù)制吹散,再次發(fā)起快照同步痕檬,陷入死循環(huán)。
解決辦法:配置合適的buffer大小參數(shù)送浊,避免快照復(fù)制死循環(huán)。
增加從節(jié)點(diǎn)
當(dāng)slave剛剛加入到集群丘跌,它必須進(jìn)行一次快照同步袭景,完成后再增量同步
無盤復(fù)制
master在進(jìn)行快照同步時唁桩,io操作會很耗時。當(dāng)磁盤不是ssd的時候耸棒,影響尤其嚴(yán)重荒澡。系統(tǒng)如果正在進(jìn)行AOF的fsync操作時,如果發(fā)生快照同步与殃,fsync將會被推遲執(zhí)行单山。
redis2.8.18版本后,redis的master會通過套接字將快照內(nèi)容發(fā)送到從節(jié)點(diǎn)幅疼,生成快照是一個遍歷的過程米奸,master會一邊遍歷內(nèi)存,一邊講內(nèi)容發(fā)送到slave爽篷。這個過程叫做無盤復(fù)制悴晰。
wait指令
redis的復(fù)制是異步操作,wait指令可以讓異步操作變成同步復(fù)制逐工,確保強(qiáng)一致性铡溪。
wait是在redis3.0之后才出現(xiàn)的。wait命令包含2個參數(shù):從節(jié)點(diǎn)數(shù)量n與時間t(毫秒)
wait 1 0? 代表無限期等待1個slave復(fù)制完成泪喊。
時間為0代表無限期等待棕硫,當(dāng)此時發(fā)生網(wǎng)絡(luò)分區(qū),那么redis會喪失可用性袒啼。
主從同步是redis分布式集群的基礎(chǔ)哈扮,也是高可用的保證。
后續(xù)文章我們會繼續(xù)探討主節(jié)點(diǎn)宕機(jī)后的恢復(fù)機(jī)制:哨兵模式瘤泪。