詳解Redis 主從復制原理


前言

  Redis 的主從復制和 MySQL 差不多,主要起着 數據備份,讀寫分離等作用。所以說主從復制對 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:6379」 和 「127.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

然后從服務器就能直接獲取數據:

127.0.0.1:12345>get msg
"hello world"

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

主從復制原理

首先,Redis 的復制分為「同步」(sync)和「命令傳播」(command propagate)兩個操作:

  • 同步操作用於將從服務器數據庫的狀態更新為主服務器所處的狀態。

  • 命令傳播則相反,它主要作用在主服務器的數據庫狀態更改時,導致主從服務器的數據庫狀態出現不一致時,讓主從回到一致的的過程。

接下來詳細說說這兩種復制。

同步

文字解說:

  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。

總結

  Redis 主從復制主要是通過 PSYNC 命令實現。復制分為 「部分復制」 以及 「完整復制」。部分復制通過 復制偏移量、復制積壓緩沖區、服務器 ID 來實現。完整復制通過 RDB 以及 復制積壓緩沖區來實現。主從復制主要解決的是 數據備份、讀寫分離的問題。

 

 

參考文章:

https://xie.infoq.cn/article/b89461f4b68913a8c3a8627b8


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM