Redis主從復(fù)制

單機(jī)有什么問(wèn)題?

單機(jī)即在一臺(tái)機(jī)器上部署一個(gè)redis節(jié)點(diǎn),主要會(huì)存在以下問(wèn)題:

1. 機(jī)器故障

如果發(fā)生機(jī)器故障,例如磁盤損壞,主板損壞等,未能在短時(shí)間內(nèi)修復(fù)好,客戶端將無(wú)法連接redis。
當(dāng)然如果僅僅是redis節(jié)點(diǎn)掛掉了,可以進(jìn)行問(wèn)題排查然后重啟,姑且不考慮這段時(shí)間對(duì)外服務(wù)的可用性,那還是可以接受的。
而發(fā)生機(jī)器故障,基本是無(wú)濟(jì)于事。除非把redis遷移到另一臺(tái)機(jī)器上,并且還要考慮數(shù)據(jù)同步的問(wèn)題。

2. 容量瓶頸

假如一臺(tái)機(jī)器是16G內(nèi)存,redis使用了12G內(nèi)存,而其他應(yīng)用還需要使用內(nèi)存,假設(shè)我們總共需要60G內(nèi)存要如何去做呢,是否有必要購(gòu)買64G內(nèi)存的機(jī)器?

3. QPS瓶頸

redis官方數(shù)據(jù)顯示可以達(dá)到10w的QPS,如果業(yè)務(wù)需要100w的QPS怎么去做呢?

關(guān)于容量瓶頸和QPS瓶頸是redis分布式需要解決的問(wèn)題,而機(jī)器故障就是高可用的問(wèn)題了。

主從復(fù)制的作用

一主一從

如圖所示左邊是Master節(jié)點(diǎn),右邊是slave節(jié)點(diǎn),即主節(jié)點(diǎn)和從節(jié)點(diǎn)。從節(jié)點(diǎn)也是可以對(duì)外提供服務(wù)的,主節(jié)點(diǎn)是有數(shù)據(jù)的,從節(jié)點(diǎn)可以通過(guò)復(fù)制操作將主節(jié)點(diǎn)的數(shù)據(jù)同步過(guò)來(lái),并且隨著主節(jié)點(diǎn)數(shù)據(jù)不斷寫(xiě)入,從節(jié)點(diǎn)數(shù)據(jù)也會(huì)做同步的更新。
整體起到的就是數(shù)據(jù)備份的效果。

一主多從

除了一主一從模型之外,redis還提供了一主多從的模型,也就是一個(gè)master可以有多個(gè)slave,也就相當(dāng)于有了多份的數(shù)據(jù)副本。
這樣可以做一個(gè)更加高可用的選擇,例如一個(gè)master和一個(gè)slave掛掉了,還能有其他的slave數(shù)據(jù)備份。

讀寫(xiě)分離

除了作為數(shù)據(jù)備份,主從模型還能做另外一個(gè)功能,就是讀寫(xiě)分離。
讓master節(jié)點(diǎn)負(fù)責(zé)提供寫(xiě)服務(wù),而將數(shù)據(jù)讀取的壓力進(jìn)行分流和負(fù)載,分?jǐn)偨o所有的從節(jié)點(diǎn)。

主從復(fù)制的作用
  1. 數(shù)據(jù)副本(備份)
  2. 擴(kuò)展讀性能(讀寫(xiě)分離)
簡(jiǎn)單總結(jié)
  1. 一個(gè)master可以有多個(gè)slave
  2. 一個(gè)slave只能有一個(gè)master
  3. 數(shù)據(jù)流向是單向的,master到slave

主從復(fù)制的配置

1. slaveof命令

如圖,想讓6380節(jié)點(diǎn)成為6379的從節(jié)點(diǎn),只需要執(zhí)行 slaveof 命令即可,此復(fù)制命令是異步進(jìn)行的,redis會(huì)自動(dòng)進(jìn)行后續(xù)數(shù)據(jù)復(fù)制的操作。
注:一般生產(chǎn)環(huán)境不允許主從節(jié)點(diǎn)都在一臺(tái)機(jī)器上,因?yàn)闆](méi)有任何的價(jià)值。

取消復(fù)制

如果6380節(jié)點(diǎn)不希望成為6379的從節(jié)點(diǎn),可以執(zhí)行 slave of on one 命令,取消后6380節(jié)點(diǎn)的數(shù)據(jù)不會(huì)被清除,只是說(shuō)后續(xù)6379節(jié)點(diǎn)新寫(xiě)入的數(shù)據(jù)不會(huì)再同步到該節(jié)點(diǎn)了。
注意:如果取消復(fù)制后想slave一個(gè)新的主節(jié)點(diǎn),新的主節(jié)點(diǎn)在同步給slave節(jié)點(diǎn)數(shù)據(jù)時(shí),會(huì)先將從節(jié)點(diǎn)的數(shù)據(jù)全部清除

2. 修改配置
# 配置主節(jié)點(diǎn)的IP和端口號(hào)
slaveof ip port
 # 從節(jié)點(diǎn)只做讀的操作,保證主從數(shù)據(jù)的一致性
slave-read-only yes 
對(duì)比

runid和復(fù)制偏移量

redis每次啟動(dòng)的時(shí)候都會(huì)有一個(gè)隨機(jī)的ID,作為一個(gè)標(biāo)識(shí),這個(gè)ID就是runid,當(dāng)然重啟之后值就改變了。
查看runid:redis-cli -p 6379 info | grep run
假如端口為6380的redis去復(fù)制6379,知道runid后,在6380上做一個(gè)標(biāo)識(shí),如果runid改變了,說(shuō)明主可能重啟了或者發(fā)生了其它變化,這時(shí)候就可以做一個(gè)全量復(fù)制把數(shù)據(jù)同步過(guò)來(lái)?;蛘叩谝淮螁?dòng)時(shí)根本不知道6379的runid,也會(huì)進(jìn)行全量復(fù)制

偏移量:數(shù)據(jù)寫(xiě)入量的字節(jié)
比如主執(zhí)行set hello world,就會(huì)有一個(gè)偏移量,然后從同步數(shù)據(jù),也會(huì)記錄一個(gè)偏移量
當(dāng)兩個(gè)偏移量達(dá)到一致時(shí)候,實(shí)際上數(shù)據(jù)就是完全同步的狀態(tài)。

啟動(dòng)主從redis,并在寫(xiě)入命令執(zhí)行前后查看主偏移量:
redis-cli -p 6379 info replication | grep master_repl

從節(jié)點(diǎn)會(huì)向主節(jié)點(diǎn)做一個(gè)上報(bào),把從節(jié)點(diǎn)的狀態(tài)同步給主節(jié)點(diǎn),這樣主節(jié)點(diǎn)就知道了從節(jié)點(diǎn)的偏移量

生產(chǎn)環(huán)境我們一般不關(guān)心這個(gè)值,有時(shí)候做監(jiān)控的時(shí)候會(huì)比對(duì)一下這兩個(gè)值的差,如果差的太多,說(shuō)明主從是有問(wèn)題的。

全量復(fù)制

全量復(fù)制主節(jié)點(diǎn)會(huì)將RDB文件也就是當(dāng)前狀態(tài)去同步給slave,在此期間主新寫(xiě)入的命令會(huì)單獨(dú)記錄起來(lái),然后當(dāng)RDB文件加載完畢之后,會(huì)通過(guò)偏移量對(duì)比將這個(gè)期間產(chǎn)生的寫(xiě)入值同步給slave,這樣就能達(dá)到數(shù)據(jù)完全同步的效果

全量復(fù)制過(guò)程
  1. 在其內(nèi)部有一條命令psync,是做同步的命令,它可以完成全量復(fù)制和部分復(fù)制的功能,當(dāng)啟動(dòng)slave節(jié)點(diǎn)時(shí),它會(huì)發(fā)送psync命令給主節(jié)點(diǎn),需要傳遞兩個(gè)參數(shù),runidoffset(偏移量),也就是從向主傳遞主節(jié)點(diǎn)的runid以及自己的偏移量,對(duì)于第一次復(fù)制而言,就直接傳遞?和 -1,當(dāng)然這個(gè)參數(shù)是由slave內(nèi)部傳的。
  2. master接收到命令后知道從希望做全量復(fù)制,主就會(huì)將自己的runid和offset傳遞給從
  3. slave節(jié)點(diǎn)保存master的基本信息
  4. master執(zhí)行bgsave生成RDB文件,并且在此期間新產(chǎn)生的寫(xiě)入命令會(huì)被記錄到repl_back_buffer(復(fù)制緩沖區(qū))
  5. 主向從傳輸RDB文件
  6. 主向從發(fā)送復(fù)制緩沖區(qū)內(nèi)容
  7. 清空從節(jié)點(diǎn)舊的數(shù)據(jù)
  8. 從節(jié)點(diǎn)加載RDB文件到內(nèi)存中,同時(shí)加載緩沖區(qū)數(shù)據(jù)
全量復(fù)制的開(kāi)銷

實(shí)際上全量復(fù)制的開(kāi)銷是非常大的,主要體現(xiàn)在如下方面

  1. bgsave時(shí)間(對(duì)cpu、 內(nèi)存、硬盤都會(huì)有一定的開(kāi)銷)
  2. RDB文件網(wǎng)絡(luò)傳輸時(shí)間(網(wǎng)絡(luò)帶寬)
  3. 從節(jié)點(diǎn)清空數(shù)據(jù)時(shí)間(根據(jù)從節(jié)點(diǎn)的數(shù)據(jù)規(guī)模)
  4. 從節(jié)點(diǎn)加載RDB的時(shí)間
  5. 可能的AOF重寫(xiě)時(shí)間(在最后從加載完RDB之后如果開(kāi)啟了AOF,會(huì)做AOF重寫(xiě))

全量復(fù)制除了上述開(kāi)銷之外,還會(huì)有個(gè)問(wèn)題:
假如master和slave網(wǎng)絡(luò)發(fā)生了抖動(dòng),那一段時(shí)間內(nèi)這些數(shù)據(jù)就會(huì)丟失,對(duì)于slave來(lái)說(shuō)這段時(shí)間master更新的數(shù)據(jù)是不知道的。最簡(jiǎn)單的方式就是再做一次全量復(fù)制,從而獲取到最新的數(shù)據(jù),在redis2.8之前是這么做的。

部分復(fù)制

部分復(fù)制,redis2.8之后提供。如果發(fā)生類似抖動(dòng)時(shí)候,可以有一種機(jī)制將這種損失降低到最低,如何實(shí)現(xiàn)的?

  1. 如果發(fā)生了抖動(dòng),相當(dāng)于連接斷開(kāi)了
  2. 主會(huì)將寫(xiě)命令記錄到緩沖區(qū),repl_back_buffer
  3. 當(dāng)slave再次去連接master時(shí)候,就是說(shuō)網(wǎng)絡(luò)抖動(dòng)結(jié)束之后,會(huì)觸發(fā)增量復(fù)制
  4. 從會(huì)執(zhí)行pysnc命令,將當(dāng)前自己的offset和主的runid傳遞給master
  5. 如果發(fā)現(xiàn)傳輸?shù)膐ffset偏移量是在buffer內(nèi)的,不在期間內(nèi)就證明你已經(jīng)錯(cuò)過(guò)了很多數(shù)據(jù),buffer也是有限的,默認(rèn)是1M,會(huì)將offset開(kāi)始到隊(duì)列結(jié)束的數(shù)據(jù)同步給從。這樣master和slave就達(dá)到了一致。

通過(guò)部分復(fù)制(增量復(fù)制)有效的降低了全量復(fù)制的開(kāi)銷。

復(fù)制的相關(guān)配置

無(wú)磁盤化復(fù)制
# 開(kāi)啟無(wú)磁盤化復(fù)制
repl-diskless-sync yes
# 當(dāng)收到第一個(gè)復(fù)制請(qǐng)求時(shí),等待 5s 后再開(kāi)始復(fù)制,因?yàn)橐雀?slave 一起連接過(guò)來(lái)
repl-diskless-sync-delay 5
復(fù)制的限制

如果在復(fù)制期間,rdb復(fù)制時(shí)間超過(guò)60秒,內(nèi)存緩沖區(qū)持續(xù)消耗超過(guò)64MB,或者一次性超過(guò)256MB,那么將會(huì)停止復(fù)制(失敗)
配置項(xiàng):client-output-buffer-limit slave 256MB 64MB 60

`

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容