- 全量復(fù)制:用于初次復(fù)制或其它無(wú)法進(jìn)行部分復(fù)制的情況,將主節(jié)點(diǎn)中的所有數(shù)據(jù)都發(fā)送給從節(jié)點(diǎn),是一個(gè)非常重型的操作,當(dāng)數(shù)據(jù)量較大時(shí),會(huì)對(duì)主從節(jié)點(diǎn)和網(wǎng)絡(luò)造成很大的開銷
- 部分復(fù)制:用于處理在主從復(fù)制中因網(wǎng)絡(luò)閃斷等原因造成的數(shù)據(jù)丟失場(chǎng)景,當(dāng)從節(jié)點(diǎn)再次連上主節(jié)點(diǎn)后,如果條件允許,主節(jié)點(diǎn)會(huì)補(bǔ)發(fā)丟失數(shù)據(jù)給從節(jié)點(diǎn)。因?yàn)檠a(bǔ)發(fā)的數(shù)據(jù)遠(yuǎn)遠(yuǎn)小于全量數(shù)據(jù),可以有效避免全量復(fù)制的過(guò)高開銷,需要注意的是,如果網(wǎng)絡(luò)中斷時(shí)間過(guò)長(zhǎng),造成主節(jié)點(diǎn)沒(méi)有能夠完整地保存中斷期間執(zhí)行的寫命令,則無(wú)法進(jìn)行部分復(fù)制,仍使用全量復(fù)制
復(fù)制偏移量
參與復(fù)制的主從節(jié)點(diǎn)都會(huì)維護(hù)自身復(fù)制偏移量。主節(jié)點(diǎn)(master)在處理完寫入命令后,會(huì)把命令的字節(jié)長(zhǎng)度做累加記錄,統(tǒng)計(jì)信息在 info relication 中的 master_repl_offset 指標(biāo)中:
127.0.0.1:6379> info replication

從節(jié)點(diǎn)(slave)每秒鐘上報(bào)自身的復(fù)制偏移量給主節(jié)點(diǎn),因此主節(jié)點(diǎn)也會(huì)保存從節(jié)點(diǎn)的復(fù)制偏移量,統(tǒng)計(jì)指標(biāo)如下:

從節(jié)點(diǎn)在接收到主節(jié)點(diǎn)發(fā)送的命令后,也會(huì)累加記錄自身的偏移量。統(tǒng)計(jì)信息在 info relication 中的 slave_repl_offset 中
復(fù)制積壓緩沖區(qū)
復(fù)制積壓緩沖區(qū)是保存在主節(jié)點(diǎn)上的一個(gè)固定長(zhǎng)度的隊(duì)列,默認(rèn)大小為1MB,當(dāng)主節(jié)點(diǎn)有連接的從節(jié)點(diǎn)(slave)時(shí)被創(chuàng)建,這時(shí)主節(jié)點(diǎn)(master)響應(yīng)寫命令時(shí),不但會(huì)把命令發(fā)送給從節(jié)點(diǎn),還會(huì)寫入復(fù)制積壓緩沖區(qū)。

在命令傳播階段,主節(jié)點(diǎn)除了將寫命令發(fā)送給從節(jié)點(diǎn),還會(huì)發(fā)送一份給復(fù)制積壓緩沖區(qū),作為寫命令的備份;除了存儲(chǔ)寫命令,復(fù)制積壓緩沖區(qū)中還存儲(chǔ)了其中的每個(gè)字節(jié)對(duì)應(yīng)的復(fù)制偏移量(offset) 。由于復(fù)制積壓緩沖區(qū)定長(zhǎng)且先進(jìn)先出,所以它保存的是主節(jié)點(diǎn)最近執(zhí)行的寫命令;時(shí)間較早的寫命令會(huì)被擠出緩沖區(qū)。
Redis全量復(fù)制
1、Redis 內(nèi)部會(huì)發(fā)出一個(gè)同步命令,剛開始是 Psync 命令,Psync ? -1表示要求 master 主機(jī)同步數(shù)據(jù)
2、主機(jī)會(huì)向從機(jī)發(fā)送 runid 和 offset,因?yàn)?slave 并沒(méi)有對(duì)應(yīng)的 offset,所以是全量復(fù)制
3、從機(jī) slave 會(huì)保存 主機(jī)master 的基本信息 save masterInfo
4、主節(jié)點(diǎn)收到全量復(fù)制的命令后,執(zhí)行bgsave(異步執(zhí)行),在后臺(tái)生成RDB文件(快照),并使用一個(gè)緩沖區(qū)(稱為復(fù)制緩沖區(qū))記錄從現(xiàn)在開始執(zhí)行的所有寫命令
5、主機(jī)send RDB 發(fā)送 RDB 文件給從機(jī)
6、發(fā)送緩沖區(qū)數(shù)據(jù)
7、刷新舊的數(shù)據(jù),從節(jié)點(diǎn)在載入主節(jié)點(diǎn)的數(shù)據(jù)之前要先將老數(shù)據(jù)清除
8、加載 RDB 文件將數(shù)據(jù)庫(kù)狀態(tài)更新至主節(jié)點(diǎn)執(zhí)行bgsave時(shí)的數(shù)據(jù)庫(kù)狀態(tài)和緩沖區(qū)數(shù)據(jù)的加載。
全量復(fù)制開銷,主要有以下幾項(xiàng)。
bgsave 時(shí)間
RDB 文件網(wǎng)絡(luò)傳輸時(shí)間
從節(jié)點(diǎn)清空數(shù)據(jù)的時(shí)間
從節(jié)點(diǎn)加載 RDB 的時(shí)間
部分復(fù)制
部分復(fù)制是 Redis 2.8 以后出現(xiàn)的,之所以要加入部分復(fù)制,是因?yàn)槿繌?fù)制會(huì)產(chǎn)生很多問(wèn)題,比如像上面的時(shí)間開銷大、無(wú)法隔離等問(wèn)題, Redis 希望能夠在 master 出現(xiàn)抖動(dòng)(相當(dāng)于斷開連接)的時(shí)候,可以有一些機(jī)制將復(fù)制的損失降低到最低
1、如果網(wǎng)絡(luò)抖動(dòng)(連接斷開 connection lost)
2、主機(jī)master 還是會(huì)寫 replbackbuffer(復(fù)制緩沖區(qū))
3、從機(jī)slave 會(huì)繼續(xù)嘗試連接主機(jī)
4、從機(jī)slave 會(huì)把自己當(dāng)前 runid 和偏移量傳輸給主機(jī) master,并且執(zhí)行 pysnc 命令同步
5、如果 master 發(fā)現(xiàn)你的偏移量是在緩沖區(qū)的范圍內(nèi),就會(huì)返回 continue 命令
同步了 offset 的部分?jǐn)?shù)據(jù),所以部分復(fù)制的基礎(chǔ)就是偏移量 offset。
注意:
正常情況下redis是如何決定是全量復(fù)制還是部分復(fù)制?
從節(jié)點(diǎn)將offset發(fā)送給主節(jié)點(diǎn)后,主節(jié)點(diǎn)根據(jù)offset和緩沖區(qū)大小決定能否執(zhí)行部分復(fù)制:
1.如果offset偏移量之后的數(shù)據(jù),仍然都在復(fù)制積壓緩沖區(qū)里,則執(zhí)行部分復(fù)制;
2.如果offset偏移量之后的數(shù)據(jù)已不在復(fù)制積壓緩沖區(qū)中(數(shù)據(jù)已被擠出),則執(zhí)行全量復(fù)制。
服務(wù)器運(yùn)行ID(runid)
每個(gè)Redis節(jié)點(diǎn)(無(wú)論主從),在啟動(dòng)時(shí)都會(huì)自動(dòng)生成一個(gè)隨機(jī)ID(每次啟動(dòng)都不一樣),由40個(gè)隨機(jī)的十六進(jìn)制字符組成;runid用來(lái)唯一識(shí)別一個(gè)Redis節(jié)點(diǎn)。 通過(guò)info server命令,可以查看節(jié)點(diǎn)的runid。
主從節(jié)點(diǎn)初次復(fù)制時(shí),主節(jié)點(diǎn)將自己的runid發(fā)送給從節(jié)點(diǎn),從節(jié)點(diǎn)將這個(gè)runid保存起來(lái);當(dāng)斷線重連時(shí),從節(jié)點(diǎn)會(huì)將這個(gè)runid發(fā)送給主節(jié)點(diǎn);主節(jié)點(diǎn)根據(jù)runid判斷能否進(jìn)行部分復(fù)制:
如果從節(jié)點(diǎn)保存的runid與主節(jié)點(diǎn)現(xiàn)在的runid相同,說(shuō)明主從節(jié)點(diǎn)之前同步過(guò),主節(jié)點(diǎn)會(huì)繼續(xù)嘗試使用部分復(fù)制(到底能不能部分復(fù)制還要看offset和復(fù)制積壓緩沖區(qū)的情況)
如果從節(jié)點(diǎn)保存的runid與主節(jié)點(diǎn)現(xiàn)在的runid不同,說(shuō)明從節(jié)點(diǎn)在斷線前同步的Redis節(jié)點(diǎn)并不是當(dāng)前的主節(jié)點(diǎn),只能進(jìn)行全量復(fù)制。
緩沖區(qū)大小調(diào)節(jié):
由于緩沖區(qū)長(zhǎng)度固定且有限,因此可以備份的寫命令也有限,當(dāng)主從節(jié)點(diǎn)offset的差距過(guò)大超過(guò)緩沖區(qū)長(zhǎng)度時(shí),將無(wú)法執(zhí)行部分復(fù)制,只能執(zhí)行全量復(fù)制。反過(guò)來(lái)說(shuō),為了提高網(wǎng)絡(luò)中斷時(shí)部分復(fù)制執(zhí)行的概率,可以根據(jù)需要增大復(fù)制積壓緩沖區(qū)的大小(通過(guò)配置repl-backlog-size)來(lái)設(shè)置;例如如果網(wǎng)絡(luò)中斷的平均時(shí)間是60s,而主節(jié)點(diǎn)平均每秒產(chǎn)生的寫命令(特定協(xié)議格式)所占的字節(jié)數(shù)為100KB,則復(fù)制積壓緩沖區(qū)的平均需求為6MB,保險(xiǎn)起見(jiàn),可以設(shè)置為12MB,來(lái)保證絕大多數(shù)斷線情況都可以使用部分復(fù)制。