溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

上次阿里面試問到Redis主從復(fù)制原理,這次終于搞明白了!

發(fā)布時(shí)間:2020-07-11 22:11:49 來源:網(wǎng)絡(luò) 閱讀:334 作者:架構(gòu)師追風(fēng) 欄目:編程語言

1.前言

Redis單節(jié)點(diǎn)存在單點(diǎn)故障,為解決單點(diǎn)問題,需要對(duì)Redis節(jié)點(diǎn)配置從節(jié)點(diǎn)。使用哨兵來監(jiān)聽主節(jié)點(diǎn)存活狀態(tài),若主節(jié)點(diǎn)掛掉,從節(jié)點(diǎn)能繼續(xù)提供緩存功能。從節(jié)點(diǎn)怎樣和主節(jié)點(diǎn)間完成數(shù)據(jù)傳遞?就是Redis的主從復(fù)制。

上次阿里面試問到Redis主從復(fù)制原理,這次終于搞明白了!

2. 主從配置及作用

臨時(shí)配置:redis-cli進(jìn)入redis從節(jié)點(diǎn)后,使用 --slaveof [masterIP] [masterPort]

永久配置:進(jìn)入從節(jié)點(diǎn)的配置文件redis.conf,增加slaveof [masterIP] [masterPort]

作用:

1)主從配置結(jié)合哨兵模式能解決單點(diǎn)故障問題,提高redis可用性

2)從節(jié)點(diǎn)僅提高讀的操作,主節(jié)點(diǎn)提供寫操作。對(duì)于讀多寫少的狀況,可給主節(jié)點(diǎn)配置多個(gè)從節(jié)點(diǎn),從而提供響應(yīng)效率

補(bǔ)充:主從復(fù)制并不是redis的橫向拓展,集群模式才是


3. 復(fù)制過程

1)從節(jié)點(diǎn)執(zhí)行slaveof [masterIP] [masterPort],保存主節(jié)點(diǎn)信息

2)從節(jié)點(diǎn)中的定時(shí)任務(wù)發(fā)現(xiàn)主節(jié)點(diǎn)信息,建立和主節(jié)點(diǎn)的socket連接

3)從節(jié)點(diǎn)發(fā)送Ping信號(hào),主節(jié)點(diǎn)返回Pong,兩邊能互相通信

4)連接建立后,主節(jié)點(diǎn)將所有數(shù)據(jù)發(fā)送給從節(jié)點(diǎn)(數(shù)據(jù)同步

5)主節(jié)點(diǎn)把當(dāng)前的數(shù)據(jù)同步給從節(jié)點(diǎn)后,便完成了復(fù)制的建立流程。接下來,主節(jié)點(diǎn)就會(huì)持續(xù)的把寫命令發(fā)送給從節(jié)點(diǎn),保證主從數(shù)據(jù)一致性

上次阿里面試問到Redis主從復(fù)制原理,這次終于搞明白了!

4. 數(shù)據(jù)同步

redis 2.8 之前使用sync [runId] [offset]同步命令,redis2.8之后使用psync [runId] [offset]命令。兩者不同在于,sync命令僅支持全量復(fù)制過程,psync支持全量和部分復(fù)制;介紹同步之前先介紹幾個(gè)概念:

runId:每個(gè)redis節(jié)點(diǎn)啟動(dòng)都會(huì)生成唯一的runId,每次redis重啟后,runId也會(huì)發(fā)生變化

offset:主節(jié)點(diǎn)和從節(jié)點(diǎn)都各自維護(hù)自己的主從復(fù)制偏移量offset,當(dāng)主節(jié)點(diǎn)有寫入命令時(shí),offset=offset+命令的字節(jié)長(zhǎng)度。從節(jié)點(diǎn)在收到主節(jié)點(diǎn)發(fā)送的命令后,也會(huì)增加自己的offset,并把自己的offset發(fā)送給主節(jié)點(diǎn)。這樣,主節(jié)點(diǎn)同時(shí)保存自己的offset,從節(jié)點(diǎn)的offset,通過對(duì)比offset來判斷主從節(jié)點(diǎn)數(shù)據(jù)是否一致

repl_backlog_size:保存在主節(jié)點(diǎn)上的一個(gè)固定長(zhǎng)度的先進(jìn)先出隊(duì)列,默認(rèn)大小為1MB

1)主節(jié)點(diǎn)發(fā)送數(shù)據(jù)給從節(jié)點(diǎn)過程中,主節(jié)點(diǎn)還會(huì)進(jìn)行一些寫操作,這時(shí)候的數(shù)據(jù)存儲(chǔ)在復(fù)制緩沖區(qū)。從節(jié)點(diǎn)同步主節(jié)點(diǎn)數(shù)據(jù)完成后,主節(jié)點(diǎn)將緩沖區(qū)的數(shù)據(jù)繼續(xù)發(fā)送給從節(jié)點(diǎn),用于部分復(fù)制;

2)主節(jié)點(diǎn)(master)響應(yīng)寫命令時(shí),不但會(huì)把命名發(fā)送給從節(jié)點(diǎn),還會(huì)寫入復(fù)制積壓緩沖區(qū),用于復(fù)制命令丟失的數(shù)據(jù)補(bǔ)救;

psync執(zhí)行流程

上次阿里面試問到Redis主從復(fù)制原理,這次終于搞明白了!

從節(jié)點(diǎn)發(fā)送psync [runId] [offset]命令,主節(jié)點(diǎn)有如下響應(yīng)

FULLRESYNC:第一次連接,進(jìn)行全量復(fù)制

CONTINUE:進(jìn)行部分復(fù)制

ERR:不支持psync命令,進(jìn)行全量復(fù)制

全量復(fù)制流程

上次阿里面試問到Redis主從復(fù)制原理,這次終于搞明白了!

1)從節(jié)點(diǎn)發(fā)送psync ? -1命令,因?yàn)榈谝淮伟l(fā)送,不知道主節(jié)點(diǎn)的runId,所以為?,因?yàn)槭堑谝淮螐?fù)制,所以offset = -1。

2)主節(jié)點(diǎn)發(fā)現(xiàn)從節(jié)點(diǎn)是第一次復(fù)制,變返回FULLRESYNC {runId} {offset},runId是主節(jié)點(diǎn)的runId,offset是主節(jié)點(diǎn)目前的offset。

3)從節(jié)點(diǎn)接收主節(jié)點(diǎn)信息后,保存到info中。

4)主節(jié)點(diǎn)在發(fā)送FULLRESYNC后,啟動(dòng)bgsave命令,生成RDB文件(數(shù)據(jù)持久化)。

5)6)主節(jié)點(diǎn)發(fā)送RDB文件給從節(jié)點(diǎn)。到從節(jié)點(diǎn)加載數(shù)據(jù)完成這段期間主節(jié)點(diǎn)的寫命令放入緩沖區(qū)。

7)從節(jié)點(diǎn)清理自己的數(shù)據(jù)庫(kù)數(shù)據(jù)。

8)從節(jié)點(diǎn)加載RDB文件,將數(shù)據(jù)保存的自己的數(shù)據(jù)庫(kù)中。

9)如果從節(jié)點(diǎn)開啟了AOF(另一種持久化方案),從節(jié)點(diǎn)會(huì)異步重寫aof文件。

部分復(fù)制流程

上次阿里面試問到Redis主從復(fù)制原理,這次終于搞明白了!

1)部分復(fù)制主要是Redis針對(duì)全量復(fù)制的過高開銷做出的一種優(yōu)化措施,使用psync {runId}{offset}命令實(shí)現(xiàn)。當(dāng)從節(jié)點(diǎn)(slave)正在復(fù)制主節(jié)點(diǎn)(master)時(shí),如果出現(xiàn)網(wǎng)絡(luò)閃斷或者命令丟失等異常情況時(shí),從節(jié)點(diǎn)會(huì)向主節(jié)點(diǎn)要求補(bǔ)發(fā)丟失的命令數(shù)據(jù),如果主節(jié)點(diǎn)的復(fù)制積壓緩沖區(qū)內(nèi)存將這部分?jǐn)?shù)據(jù)則直接發(fā)送給從節(jié)點(diǎn),這樣就可以保持主從節(jié)點(diǎn)復(fù)制的一致性。補(bǔ)發(fā)的這部分?jǐn)?shù)據(jù)一般遠(yuǎn)遠(yuǎn)小于全量數(shù)據(jù)。

2)主從連接中斷期間主節(jié)點(diǎn)依然響應(yīng)命令,但因復(fù)制連接中斷命令無法發(fā)送給從節(jié)點(diǎn),不過主節(jié)點(diǎn)內(nèi)部存在的復(fù)制積壓緩沖區(qū),依然可以保存最近一段時(shí)間的寫命令數(shù)據(jù),默認(rèn)最大緩存1MB。當(dāng)從節(jié)點(diǎn)網(wǎng)絡(luò)恢復(fù)后,從節(jié)點(diǎn)會(huì)再次連上主節(jié)點(diǎn)。

3)當(dāng)主從連接恢復(fù)后,由于從節(jié)點(diǎn)之前保存了自身已復(fù)制的偏移量和主節(jié)點(diǎn)的運(yùn)行ID。因此會(huì)把它們當(dāng)做psync參數(shù)發(fā)送個(gè)主節(jié)點(diǎn),要求進(jìn)行部分復(fù)制操作。

4)主節(jié)點(diǎn)接到psync命令后首先核對(duì)參數(shù)runId是否與自身一致,如果一致,說明之前復(fù)制的是當(dāng)前主節(jié)點(diǎn);之后根據(jù)參數(shù)offset在自身復(fù)制積壓緩沖區(qū)查找,如果偏移量之后的數(shù)據(jù)存在緩沖區(qū)中,則對(duì)從節(jié)點(diǎn)發(fā)送+COUTINUE響應(yīng),表示可以進(jìn)行部分復(fù)制。因?yàn)榫彌_區(qū)大小固定,若發(fā)生緩存溢出,則要進(jìn)行全量復(fù)制。

5)主節(jié)點(diǎn)根據(jù)偏移量把復(fù)制積壓緩沖區(qū)里的數(shù)據(jù)發(fā)送給從節(jié)點(diǎn),保證主從復(fù)制進(jìn)入正常狀態(tài)。
歡迎大家關(guān)注我的公種浩【程序員追風(fēng)】,文章都會(huì)在里面更新,整理的資料也會(huì)放在里面。

上次阿里面試問到Redis主從復(fù)制原理,這次終于搞明白了!

5. 補(bǔ)充

Redis故障處理

若主節(jié)點(diǎn)掛掉后,再次重啟,runid的值會(huì)變。此時(shí)從節(jié)點(diǎn)的發(fā)送psync命令,會(huì)提示找不到原runid,則會(huì)再進(jìn)行一次全量復(fù)制。為避免這種狀況,使用Redis故障轉(zhuǎn)移機(jī)制,主節(jié)點(diǎn)掛掉后,從節(jié)點(diǎn)升級(jí)為主節(jié)點(diǎn)。如哨兵模式。

最后

歡迎大家一起交流,喜歡文章記得點(diǎn)個(gè)贊喲,感謝支持!


向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI