天天看點

Redis的複制原理

為什麼要複制?

無論是使用AOF持久化還是RDB持久化,将資料持久化到硬碟上都是非常有必要的,但是除了進行資料的持久化之外,還必須對持久化後的檔案進行備份。最好是備份到不同的伺服器上,這樣才能避免資料丢失事故的發生。

Redis複制的配置

slaveof host port
可以通過執行slaveof指令或者在redis.conf檔案中配置slaveof選項,
讓一個伺服器去複制(replicate)另一個伺服器,被複制的伺服器為
主伺服器(master),複制的伺服器成為從伺服器(slave)
假設現在有兩台Redis伺服器
127.0.0.1 6379和127.0.0.1 6380
在127.0.0.1 6380伺服器上執行
127.0.0.1:6380> slaveof 127.0.0.1 6379
OK
這樣伺服器127.0.0.1 6380将成為127.0.0.1 6379的從伺服器
進行複制的主從伺服器上将儲存相同的資料
在主伺服器上執行
127.0.0.1:6379> set msg hello
OK
127.0.0.1:6379> get msg
"hello"
在主伺服器上可以擷取到值,在從伺服器上也可以擷取到
127.0.0.1:6380> get msg
"hello"
           

Redis複制功能的實作

Redis的複制分為同步和指令傳播兩個操作

同步:将從伺服器的資料庫狀态更新至主伺服器目前所屬的數控狀态
指令傳播:主伺服器資料庫修改,主從伺服器資料庫狀态不一緻,讓主從伺服器
資料庫狀态重新回到一緻狀态
           

同步:

當用戶端向伺服器發送slaveof指令,要求複制主伺服器,從伺服器先執行同步操作。注意:從伺服器在進行同步的時候,會清除自己的所有資料!原有資料丢失,替換為主伺服器發來的資料

sync指令
從伺服器對主伺服器的同步需要向主伺服器發送sync指令。
同步的步驟
1,從伺服器向主伺服器發送SYNC指令。
2,主伺服器收到PSYNC指令會執行BGSAVE指令,在背景建立RDB檔案,
并使用一個緩沖區記錄從現在開始執行的所有寫指令。
3,主伺服器會将生成的RDB檔案發送給從伺服器,從伺服器接收并載入RDB檔案,
從伺服器的所有資料丢失,替換為主伺服器發來的RDB檔案中的資料。
4,主伺服器将緩沖區的寫指令發送給從伺服器,從伺服器執行主伺服器發來的寫指令
           
Redis的複制原理

指令傳播

在同步操作執行完畢之後,主從伺服器資料庫狀态一緻,但是這種一緻不是一成不變,當主伺服器執行用戶端發送的寫指令,主伺服器的資料庫狀态就會被修改,導緻主從伺服器狀态不一緻。這時候主伺服器就會進行指令傳播,将自己執行的寫指令發送給從伺服器,從伺服器接收并執行主伺服器發來的寫指令,使得主從伺服器資料庫狀态再次一緻。

SYNC指令的缺陷:

當從伺服器斷開的時候,主伺服器在從伺服器斷開到重新連接配接的是可能會繼續
執行寫指令。當從伺服器重新連接配接的時候,向主伺服器發送SYNC指令。
再次進行同步操作,使得主從伺服器資料庫狀态再次一緻。
但是從伺服器需要的僅僅隻是在斷線到重連這段時間主伺服器執行的寫指令,
為了彌補這一小部分缺失的資料,确需要主服務重新執行一次SYNC指令,而
SYNC指令是非常消耗資源的操作,這樣是很低效的。
           

PSYNC指令:

為了解決斷線重連複制的低效問題,Redis從2.8版本開始,使用PSYNC指令來代替SYNC指令來執行複制的同步操作

PSYNC具有完整重同步和部分重同步

完整重同步:和sync指令的同步執行的步驟一緻,用于處理初次複制的情況
部分重同步:用來處理斷線重連後的複制情況,如果情況允許,當伺服器在斷線
    後重新連接配接主服務時,主伺服器可以将從伺服器斷開期間執行的寫指令
    發送給從伺服器,從伺服器隻要接收并執行這些寫指令,就可以和主伺服器
    的資料庫一緻狀态保持。
           

主從伺服器執行部分重同步的過程

從伺服器重連之後向主伺服器發送FSYNC指令
主伺服器向從伺服器傳回+CONTUNUE回複,表示執行部分重同步
從伺服器接收+CONTINUE回複,準備執行部分部分重同步
主伺服器向從伺服器發送從伺服器斷開期間的執行寫指令
從伺服器接收并執行主伺服器發來的寫指令
主從伺服器的資料庫狀态一緻
           
Redis的複制原理

部分重同步的實作

部分重同步由三個部分構成
1.主從伺服器的複制偏移量(replication offset)
2.主伺服器的複制積壓緩沖區
3.伺服器的運作ID
           

複制偏移量(replication offset)

執行複制的雙方-主從伺服器都會維護一個複制偏移量

主伺服器每次向伺服器發送N個位元組的資料,就将自己的複制偏移量加N
從伺服器每次接收到主伺服器發送的N個位元組資料,也将自己的複制偏移量加N
通過對比主從伺服器的複制偏移量,就能知道主從伺服器的資料庫狀态是
否屬于一緻的狀态。
           

當從伺服器重連之後,主伺服器如何将從伺服器斷開期間執行的寫指令再補償給從伺服器呢?這就需要複制積壓緩沖區

複制積壓緩沖區

複制積壓緩沖區是主伺服器維護的一個固定長度的FIFO隊列
當主伺服器進行指令傳播的時候,不僅會将寫指令發送給從伺服器,還會将寫指令
入隊到複制積壓緩沖區裡面
           
Redis的複制原理

當從伺服器連接配接上伺服器時,會通過PSYNC指令将自己的複制偏移量發送給主伺服器,主伺服器會根據這個複制偏移量來決定是執行完全重同步還是部分重同步。

如果複制偏移量offset+1後的資料還在複制積壓緩沖區裡面,就執行部分重同步
反之則執行完全重同步
           

伺服器運作ID

每個Redis伺服器都有自己的運作ID,由40個随機的十六進制字元組成
           

在首次複制的時候,主伺服器會将自己的運作ID發送給從伺服器,從伺服器儲存起來。

在斷線重連之後,從伺服器會向主伺服器發送之前儲存的運作ID。如果和目前重連的主伺服器運作ID相同。則說明斷線之前從伺服器複制的就是這個主伺服器。

繼續閱讀