詳解Redis主從複製原理

文章首發於公衆號 「蘑菇睡不着」面試

前言

Redis 的主從複製和 MySQL 差很少,主要起着 數據備份,讀寫分離等做用。因此說主從複製對 Redis 來講很是重要,而不管是面試仍是工做總,瞭解 Redis主從複製 底層實現有很是有必要,那麼接下來就和你們來看看 Redis 主從複製是怎麼實現的吧。redis

什麼是 Redis 主從複製?

  在 Redis 中,咱們能夠經過 SLAVEOF 命令或者 slaveof 選項,讓一個服務器去複製另外一個服務器,被複制的服務器稱爲「主服務器」,發起複製的服務器稱爲「從服務器」,由兩種服務器組成的模式稱爲「主從複製」。數據庫

  Redis 主從複製有如下特色:服務器

  • Redis 使用異步複製,slave 和 master 之間異步地確認處理的數據量。
  • 一個 master 能夠擁有多個 slave。
  • slave 能夠接受其餘 slave 的鏈接。除了多個 slave 能夠鏈接到同一個 master 以外, slave 之間也能夠像層疊狀的結構(cascading-like structure)鏈接到其餘 slave 。自 Redis 4.0 起,全部的 sub-slave 將會從 master 收到徹底同樣的複製流。
  • Redis 複製在 master 側是非阻塞的。這意味着 master 在一個或多個 slave 進行初次同步或者是部分重同步時,能夠繼續處理查詢請求。
  • 複製在 slave 側大部分也是非阻塞的。固然這個是可配的,若是在 redis.conf配置是非阻塞的,可使用舊數據集處理查詢請求;若是配置的是阻塞的,slave 會返回一個 error 給客戶端。

怎麼實現主從複製?

假設如今有兩個 Redis 服務器,地址分別爲 127.0.0.1:6379127.0.0.1:12345,若是在服務器 127.0.0.1:12345 執行如下命令:網絡

127.0.0.1:12345> SLAVEOF 127.0.0.1 6379
OK

那麼服務器127.0.0.1:12345就是127.0.0.1:6379 的從服務器。主從服務器的數據會保持一致
好比主服務器存儲數據:異步

127.0.0.1:6379> set msg "hello world"
OK

而後從服務器就能直接獲取數據:code

127.0.0.1:12345>get msg
"hello world"

刪除數據也是同樣,主從會保持一致。隊列

主從複製原理

首先,Redis 的複製分爲同步(sync)和命令傳播(command propagate)兩個操做:get

  • 同步操做用於將從服務器數據庫的狀態更新爲主服務器所處的狀態。
  • 命令傳播則相反,它主要做用在主服務器的數據庫狀態更改時,致使主從服務器的數據庫狀態出現不一致時,讓主從回到一致的的過程。

接下來詳細說說這兩種複製。同步

同步

文字解說:

  1. 客戶端向從服務器發送 SLAVEOF 命令,先是判斷是不是第一次複製,第一次是複製通常是剛開始組建主從關係。
  2. 是第一次複製:從服務器會向主服務器發送 PSYNC ? -1 命令,請求主服務器執行完整重同步操做。
  3. 主服務器接到完整重同步請求以後,將在後臺執行 BGSAVE 命令,在後臺生成一個 RDB 文件,並使用一個複製積壓緩衝區記錄從如今開始執行的全部寫命令。
  4. BGSAVE 命令執行完畢以後,主服務器會將 RDB 文件以及 緩衝區中記錄的寫命令發送給從服務器,還會向從服務器返回 +FULLRESYNC [主服務器ID] [複製偏移量](和圖中的 偏移量 是一個)。
  5. 從服務器接收到後,會載入 RDB 文件,並執行 主服務器給的 寫命令,以此來達到和主服務器一致的數據狀態。
  6. 若是不是第一次複製,那麼說明從服務器多是斷線,致使和主服務器數據狀態不一致,須要同步主服務器的數據。那麼從服務器會按照下面的步驟來請求部分同步。
  7. 向主服務器發送 PSYNC [主服務器ID] [複製偏移量](這個是第一次複製時主服務器傳過來的),主服務器ID 時斷線前的主服務器,用於定位去同步那個主服務器的;複製偏移量是上一次同步的位置,用於定位具體的同步位置的。
  8. 主服務器接收到從服務器的命令後,並找到相應同步的位置後,會給從服務器發送 +CONTINUE 命令,表示將於從服務器執行部分同步操做,以後主服務器會將保存在複製積壓緩衝區對應 複製偏移量以後的全部數據發送給從服務器,可是若是找不到偏移量以後的數據,就會進行完整同步,這樣就可讓從服務器達到和主服務器一致的狀態。

命令傳播

主從服務器同步成功後,並不會一致保持這個狀態,主服務器可能會執行寫命令,這也主從數據就不知一致了。
爲了處理這種問題,主服務器會把本身執行的寫命令發送給從服務器,當從服務器執行完這些命令以後,主從服務器的數據就一致了

在命令傳播階段,從服務器默認會以每秒一次的頻率,向主服務器發送命令:
REPLCONF ACK <replication_offset>
<replication_offset> 是從服務器當前的複製偏移量。
發送 REPLCONF ACK 命令對於主從服務器有三個做用:

  • 檢測主從服務器的網絡狀態。
  • 輔助實現 min-slaves 選項。
  • 檢測命令丟失。

關鍵詞講解

  1. 主服務器ID:用於標識一個服務器。
  • 每一個服務器,不管是主服務器仍是從服務器都有屬於本身獨一無二的 服務器ID。
  • ID 在服務器啓動時生成,由 40 個隨機的十六進制字符組成。
  1. 複製積壓緩衝區:複製積壓緩衝區是由主服務器維護的一個固定長度、先進先出(FIFO)隊列,默認大小爲 1MB。以下:
偏移量 ... 10086 10087 10088 10089 ...
字節值 ... 3 '\r' '\n' '$' ...

總結

Redis 主從複製主要是經過 PSYNC 命令實現。
複製分爲 部分複製 以及 完整複製
部分複製經過 複製偏移量、複製積壓緩衝區、服務器ID來實現。
完整複製經過 RDB 以及 複製積壓緩衝區來實現。
主從複製主要解決的是 數據備份、讀寫分離的問題。

最後

若是以爲文章對你有幫助,點贊、關注、轉發 通通走起來~

能夠去公衆號 蘑菇睡不着 看看,更多精彩內容等你。

相關文章
相關標籤/搜索