Redis 舊版復(fù)制功能的實(shí)現(xiàn)

2018-08-02 14:54 更新

Redis 的復(fù)制功能分為同步(sync)和命令傳播(command propagate)兩個(gè)操作:

  • 其中, 同步操作用于將從服務(wù)器的數(shù)據(jù)庫(kù)狀態(tài)更新至主服務(wù)器當(dāng)前所處的數(shù)據(jù)庫(kù)狀態(tài)。
  • 而命令傳播操作則用于在主服務(wù)器的數(shù)據(jù)庫(kù)狀態(tài)被修改, 導(dǎo)致主從服務(wù)器的數(shù)據(jù)庫(kù)狀態(tài)出現(xiàn)不一致時(shí), 讓主從服務(wù)器的數(shù)據(jù)庫(kù)重新回到一致狀態(tài)。

本節(jié)接下來(lái)將對(duì)同步和命令傳播兩個(gè)操作進(jìn)行詳細(xì)的介紹。

同步

當(dāng)客戶端向從服務(wù)器發(fā)送 SLAVEOF 命令, 要求從服務(wù)器復(fù)制主服務(wù)器時(shí), 從服務(wù)器首先需要執(zhí)行同步操作, 也即是, 將從服務(wù)器的數(shù)據(jù)庫(kù)狀態(tài)更新至主服務(wù)器當(dāng)前所處的數(shù)據(jù)庫(kù)狀態(tài)。

從服務(wù)器對(duì)主服務(wù)器的同步操作需要通過向主服務(wù)器發(fā)送 SYNC 命令來(lái)完成, 以下是 SYNC 命令的執(zhí)行步驟:

  1. 從服務(wù)器向主服務(wù)器發(fā)送 SYNC 命令。
  2. 收到 SYNC 命令的主服務(wù)器執(zhí)行 BGSAVE 命令, 在后臺(tái)生成一個(gè) RDB 文件, 并使用一個(gè)緩沖區(qū)記錄從現(xiàn)在開始執(zhí)行的所有寫命令。
  3. 當(dāng)主服務(wù)器的 BGSAVE 命令執(zhí)行完畢時(shí), 主服務(wù)器會(huì)將 BGSAVE 命令生成的 RDB 文件發(fā)送給從服務(wù)器, 從服務(wù)器接收并載入這個(gè) RDB 文件, 將自己的數(shù)據(jù)庫(kù)狀態(tài)更新至主服務(wù)器執(zhí)行 BGSAVE 命令時(shí)的數(shù)據(jù)庫(kù)狀態(tài)。
  4. 主服務(wù)器將記錄在緩沖區(qū)里面的所有寫命令發(fā)送給從服務(wù)器, 從服務(wù)器執(zhí)行這些寫命令, 將自己的數(shù)據(jù)庫(kù)狀態(tài)更新至主服務(wù)器數(shù)據(jù)庫(kù)當(dāng)前所處的狀態(tài)。

圖 IMAGE_SYNC 展示了 SYNC 命令執(zhí)行期間, 主從服務(wù)器的通信過程。

表 TABLE_SYNC_EXAMPLE 展示了一個(gè)主從服務(wù)器進(jìn)行同步的例子。

時(shí)間 主服務(wù)器 從服務(wù)器
T0 服務(wù)器啟動(dòng)。 服務(wù)器啟動(dòng)。
T1 執(zhí)行 SET k1 v1 。  
T2 執(zhí)行 SET k2 v2 。  
T3 執(zhí)行 SET k3 v3 。  
T4   向主服務(wù)器發(fā)送 SYNC 命令。
T5 接收到從服務(wù)器發(fā)來(lái)的 SYNC 命令, 執(zhí)行 BGSAVE 命令, 創(chuàng)建包含鍵 k1 、 k2 、 k3 的 RDB 文件, 并使用緩沖區(qū)記錄接下來(lái)執(zhí)行的所有寫命令。  
T6 執(zhí)行 SET k4 v4 , 并將這個(gè)命令記錄到緩沖區(qū)里面。  
T7 執(zhí)行 SET k5 v5 , 并將這個(gè)命令記錄到緩沖區(qū)里面。  
T8 BGSAVE 命令執(zhí)行完畢, 向從服務(wù)器發(fā)送 RDB 文件。  
T9   接收并載入主服務(wù)器發(fā)來(lái)的 RDB 文件 , 獲得 k1 、 k2 、 k3 三個(gè)鍵。
T10 向從服務(wù)器發(fā)送緩沖區(qū)中保存的寫命令 SET k4 v4 和 SET k5v5 。  
T11   接收并執(zhí)行主服務(wù)器發(fā)來(lái)的兩個(gè) SET 命令, 得到 k4 和 k5 兩個(gè)鍵。
T12 同步完成, 現(xiàn)在主從服務(wù)器兩者的數(shù)據(jù)庫(kù)都包含了鍵 k1 、k2 、 k3 、 k4 和 k5 。 同步完成, 現(xiàn)在主從服務(wù)器兩者的數(shù)據(jù)庫(kù)都包含了鍵 k1 、 k2 、k3 、 k4 和 k5 。

命令傳播

在同步操作執(zhí)行完畢之后, 主從服務(wù)器兩者的數(shù)據(jù)庫(kù)將達(dá)到一致狀態(tài), 但這種一致并不是一成不變的 —— 每當(dāng)主服務(wù)器執(zhí)行客戶端發(fā)送的寫命令時(shí), 主服務(wù)器的數(shù)據(jù)庫(kù)就有可能會(huì)被修改, 并導(dǎo)致主從服務(wù)器狀態(tài)不再一致。

舉個(gè)例子, 假設(shè)一個(gè)主服務(wù)器和一個(gè)從服務(wù)器剛剛完成同步操作, 它們的數(shù)據(jù)庫(kù)都保存了相同的五個(gè)鍵 k1 至 k5 , 如圖 IMAGE_CONSISTENT 所示。

如果這時(shí), 客戶端向主服務(wù)器發(fā)送命令 DEL k3 , 那么主服務(wù)器在執(zhí)行完這個(gè) DEL 命令之后, 主從服務(wù)器的數(shù)據(jù)庫(kù)將出現(xiàn)不一致: 主服務(wù)器的數(shù)據(jù)庫(kù)已經(jīng)不再包含鍵 k3 , 但這個(gè)鍵卻仍然包含在從服務(wù)器的數(shù)據(jù)庫(kù)里面, 如圖 IMAGE_INCONSISTENT 所示。

為了讓主從服務(wù)器再次回到一致狀態(tài), 主服務(wù)器需要對(duì)從服務(wù)器執(zhí)行命令傳播操作: 主服務(wù)器會(huì)將自己執(zhí)行的寫命令 —— 也即是造成主從服務(wù)器不一致的那條寫命令 —— 發(fā)送給從服務(wù)器執(zhí)行, 當(dāng)從服務(wù)器執(zhí)行了相同的寫命令之后, 主從服務(wù)器將再次回到一致狀態(tài)。

在上面的例子中, 主服務(wù)器因?yàn)閳?zhí)行了命令 DEL k3 而導(dǎo)致主從服務(wù)器不一致, 所以主服務(wù)器將向從服務(wù)器發(fā)送相同的命令 DEL k3 : 當(dāng)從服務(wù)器執(zhí)行完這個(gè)命令之后, 主從服務(wù)器將再次回到一致狀態(tài) —— 現(xiàn)在主從服務(wù)器兩者的數(shù)據(jù)庫(kù)都不再包含鍵 k3 了, 如圖 IMAGE_PROPAGATE_DEL_k3 所示。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)