1. 程式人生 > >【docker】效能優化-redis之【主從複製】全量複製和部分複製

【docker】效能優化-redis之【主從複製】全量複製和部分複製


概念:

全量複製:用於初次複製或其它無法進行部分複製的情況,將主節點中的所有資料都發送給從節點,是一個非常重型的操作,當資料量較大時,會對主從節點和網路造成很大的開銷

部分複製:用於處理在主從複製中因網路閃斷等原因造成的資料丟失場景,當從節點再次連上主節點後,如果條件允許,主節點會補發丟失資料給從節點。因為補發的資料遠遠小於全量資料,可以有效避免全量複製的過高開銷,需要注意的是,如果網路中斷時間過長,造成主節點沒有能夠完整地儲存中斷期間執行的寫命令,則無法進行部分複製,仍使用全量複製

 

複製偏移量

  參與複製的主從節點都會維護自身複製偏移量。主節點(master)在處理完寫入命令後,會把命令的位元組長度做累加記錄,統計資訊在 info relication 中的 master_repl_offset 指標中:

127.0.0.1:6379> info replication

從節點(slave)每秒鐘上報自身的複製偏移量給主節點,因此主節點也會儲存從節點的複製偏移量,統計指標如下:

從節點在接收到主節點發送的命令後,也會累加記錄自身的偏移量。統計資訊在 info relication 中的 slave_repl_offset 中

複製積壓緩衝區

複製積壓緩衝區是儲存在主節點上的一個固定長度的佇列,預設大小為1MB【不建議很大】,當主節點有連線的從節點(slave)時被建立,這時主節點(master)響應寫命令時,不但會把命令傳送給從節點,還會寫入複製積壓緩衝區。

在命令傳播階段,主節點除了將寫命令傳送給從節點,還會發送一份給複製積壓緩衝區,作為寫命令的備份;除了儲存寫命令,複製積壓緩衝區中還儲存了其中的每個位元組對應的複製偏移量(offset) 。由於複製積壓緩衝區定長且先進先出,所以它儲存的是主節點最近執行的寫命令;時間較早的寫命令會被擠出緩衝區【看自己配置的大小】。

過程如下:

1、Redis 內部會發出一個同步命令,剛開始是 Psync 命令,Psync ? -1表示要求 master 主機同步資料

  1. 主機會向從機發送 runid 和 offset,因為 slave 並沒有對應的 offset,所以是全量複製
  2. 從機 slave 會儲存 主機master 的基本資訊 save masterInfo
  3. 主節點收到全量複製的命令後,執行bgsave(非同步執行),在後臺生成RDB檔案(快照),並使用一個緩衝區(稱為複製緩衝區)記錄從現在開始執行的所有寫命令
  4. 主機send RDB 傳送 RDB 檔案給從機
  5. 傳送緩衝區資料
  6. 重新整理舊的資料,從節點在載入主節點的資料之前要先將老資料清除

載入 RDB 檔案將資料庫狀態更新至主節點執行bgsave時的資料庫狀態和緩衝區資料的載入。

全量複製開銷,主要有以下幾項。

bgsave 時間

RDB 檔案網路傳輸時間

從節點清空資料的時間

從節點載入 RDB 的時間

部分複製

部分複製是 Redis 2.8 以後出現的,之所以要加入部分複製,是因為全量複製會產生很多問題,比如像上面的時間開銷大、無法隔離等問題, Redis 希望能夠在 master 出現抖動(相當於斷開連線)的時候,可以有一些機制將複製的損失降低到最低

redis是如何決定是全量複製還是部分複製

從節點將offset傳送給主節點後,主節點根據offset和緩衝區大小決定能否執行部分複製:

如果offset偏移量之後的資料,仍然都在複製積壓緩衝區裡,則執行部分複製;

如果offset偏移量之後的資料已不在複製積壓緩衝區中(資料已被擠出),則執行全量複製。

 緩衝區大小調節:

由於緩衝區長度固定且有限,因此可以備份的寫命令也有限,當主從節點offset的差距過大超過緩衝區長度時,將無法執行部分複製,只能執行全量複製。反過來說,為了提高網路中斷時部分複製執行的概率,可以根據需要增大複製積壓緩衝區的大小(通過配置repl-backlog-size)來設定;例如如果網路中斷的平均時間是60s,而主節點平均每秒產生的寫命令(特定協議格式)所佔的位元組數為100KB,則複製積壓緩衝區的平均需求為6MB,保險起見,可以設定為12MB,來保證絕大多數斷線情況都可以使用部分複製。

伺服器執行ID(runid)

每個Redis節點(無論主從),在啟動時都會自動生成一個隨機ID(每次啟動都不一樣),由40個隨機的十六進位制字元組成;runid用來唯一識別一個Redis節點。 通過info server命令,可以檢視節點的runid:

主從節點初次複製時,主節點將自己的runid傳送給從節點,從節點將這個runid儲存起來;當斷線重連時,從節點會將這個runid傳送給主節點;主節點根據runid判斷能否進行部分複製:

如果從節點儲存的runid與主節點現在的runid相同,說明主從節點之前同步過,主節點會繼續嘗試使用部分複製(到底能不能部分複製還要看offset和複製積壓緩衝區的情況)

如果從節點儲存的runid與主節點現在的runid不同,說明從節點在斷線前同步的Redis節點並不是當前的主節點,只能進行全量複製。