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īng)顟B(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ù)器的同步操作需要通過(guò)向主服務(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)在開(kāi)始執(zhí)行的所有寫(xiě)命令。
  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ū)里面的所有寫(xiě)命令發(fā)送給從服務(wù)器, 從服務(wù)器執(zhí)行這些寫(xiě)命令, 將自己的數(shù)據(jù)庫(kù)狀態(tài)更新至主服務(wù)器數(shù)據(jù)庫(kù)當(dāng)前所處的狀態(tài)。

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

表 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í)行的所有寫(xiě)命令。  
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ū)中保存的寫(xiě)命令 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īng)顟B(tài), 但這種一致并不是一成不變的 —— 每當(dāng)主服務(wù)器執(zhí)行客戶端發(fā)送的寫(xiě)命令時(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īng)顟B(tài), 主服務(wù)器需要對(duì)從服務(wù)器執(zhí)行命令傳播操作: 主服務(wù)器會(huì)將自己執(zhí)行的寫(xiě)命令 —— 也即是造成主從服務(wù)器不一致的那條寫(xiě)命令 —— 發(fā)送給從服務(wù)器執(zhí)行, 當(dāng)從服務(wù)器執(zhí)行了相同的寫(xiě)命令之后, 主從服務(wù)器將再次回到一致?tīng)顟B(tài)。

在上面的例子中, 主服務(wù)器因?yàn)閳?zhí)行了命令 DEL k3 而導(dǎo)致主從服務(wù)器不一致, 所以主服務(wù)器將向從服務(wù)器發(fā)送相同的命令 DEL k3 : 當(dāng)從服務(wù)器執(zhí)行完這個(gè)命令之后, 主從服務(wù)器將再次回到一致?tīng)顟B(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)