redis學習筆記——主從同步(複製)

來源:互聯網
上載者:User

標籤:

在Redis中,使用者可以通過執行SLAVEOF命令或者設定slaveof選項,讓一個伺服器去複製(replicate)另一個伺服器,我們稱呼被複製的伺服器為主伺服器(master),而對主伺服器進行複製的伺服器則被稱為從伺服器(slave),。

假設現在有兩個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則會成為127.0.0.1:12345的主伺服器。

(記得去http://redisdoc.com/topic/replication.html上將一些操作進行補充)

本文是按照《Redis設計與實現》一書所整理的,感覺原書講的非常棒,所以下面的這部分的知識將按照原書的邏輯進行介紹:

先介紹舊版複製功能在處理斷線後重新串連的從伺服器時,會遇上怎樣的低效情況。新版複製功能是如何通過部分重同步來解決舊版複製功能的低效問題的,並說明部分重同步的實現原理。

舊版複製功能的實現

Redis的複製功能分為同步(sync)和命令傳播(command propagate)兩個操作:

  • 同步操作用於將從伺服器的資料庫狀態更新至主伺服器當前所處的資料庫狀態;
  • 命令傳播操作則用於在主伺服器的資料庫狀態被修改,導致主從伺服器的資料庫狀態出現不一致時,讓主從伺服器的資料庫重新回到一致狀態。
同步

當用戶端向從伺服器發送SLAVEOF命令,要求從伺服器複製主伺服器時,從伺服器首先需要執行同步操作,也即是,將從伺服器的資料庫狀態更新至主伺服器當前所處的資料庫狀態。

從伺服器對主伺服器的同步操作需要通過向主伺服器發送SYNC命令來完成,以下是SYNC命令的執行步驟:

  1. 從伺服器向主伺服器發送SYNC命令;
  2. 收到SYNC命令的主伺服器執行BGSAVE命令,在後台產生一個RDB檔案,並使用一個緩衝區記錄從現在開始執行的所有寫命令;
  3. 當主伺服器的BGSAVE命令執行完畢時,主伺服器會將BGSAVE命令產生的RDB檔案發送給從伺服器,從伺服器接收並載入這個RDB檔案,將自己的資料庫狀態更新至主伺服器執行BGSAVE命令時的資料庫狀態
  4. 主伺服器將記錄在緩衝區裡面的所有寫命令發送給從伺服器,從伺服器執行這些寫命令,將自己的資料庫狀態更新至主伺服器資料庫當前所處的狀態。
命令傳播

在執行完同步操作之後,主從伺服器之間資料庫狀態已經相同了。但這個狀態並非一成不變,如果祝伺服器執行了寫操作,那麼主伺服器的資料庫狀態就會修改,並導致主從伺服器狀態不再一致。

所以為了讓主從伺服器再次回到一致狀態,主伺服器需要對從伺服器執行命令傳播操作:主伺服器會將自己執行的寫命令,也即是造成主從伺服器不一致的那條寫命令,發送給從伺服器執行,當從伺服器執行了相同的寫命令之後,主從伺服器將再次回到一致狀態。

舊版複製功能的缺陷

在Redis中,從伺服器對主伺服器的複製可以分為以下兩種情況:

  • 初次複製:從伺服器以前沒有複製過任何主伺服器,或者從伺服器當前要複製的主伺服器和上一次複製的主伺服器不同;
  • 斷線後重複製:處於命令傳播階段的主從伺服器因為網路原因而中斷了複製,但從伺服器通過自動重串連重新連上了主伺服器,並繼續複製主伺服器。

對於初次複製來說,舊版複製功能能夠很好地完成任務,但對於斷線後重複製來說,舊版複製功能雖然也能讓主從伺服器重新回到一致狀態,但效率卻非常低。

我們給出一個例子進行說明:

從伺服器終於重新串連上主伺服器,因為這時主從伺服器的狀態已經不再一致,所以從伺服器將向主伺服器發送SYNC命令,而主伺服器會將包含鍵k1至鍵k10089的RDB檔案發送給從伺服器,從伺服器通過接收和載入這個RDB檔案來將自己的資料庫更新至主伺服器資料庫當前所處的狀態。

上面給出的例子可能有一點理想化,因為在主從伺服器斷線期間,主伺服器執行的寫命令可能會有成百上千個之多,而不僅僅是兩三個寫命令。但總的來說,主從伺服器斷開的時間越短,主伺服器在斷線期間執行的寫命令就越少,而執行少量寫命令所產生的資料量通常比整個資料庫的資料量要少得多,在這種情況下,為了讓從伺服器補足一小部分缺失的資料,卻要讓主從伺服器重新執行一次SYNC命令,這種做法無疑是非常低效的。

SYNC命令是一個非常耗費資源的操作

SYNC命令是非常消耗資源的,因為每次執行SYNC命令,主從伺服器需要執行一下操作:

  1. 主伺服器需要執行BGSAVE命令來產生RDB檔案,這個產生操作會耗費主伺服器大量的CPU、記憶體和磁碟I/O資源;
  2. 主伺服器需要將自己產生的RDB檔案發送給從伺服器,這個發送操作會耗費主從伺服器大量的網路資源(頻寬和流量),並對主伺服器響應命令請求的時間產生影響;
  3. 接收到RDB檔案的從伺服器需要載入主伺服器發來的RDB檔案,並且在載入期間,從伺服器會因為阻塞而沒辦法處理命令請求

SYNC是一個如此消耗資源的命令,所以Redis最好在真需要的時候才需要執行SYNC命令。

新版複製功能的實現

為瞭解決舊版複製功能在處理斷線重複製情況時的低效問題,Redis從2.8版本開始,使用PSYNC命令代替SYNC命令來執行複製時的同步操作。

PSYNC命令具有完整重同步(full resynchronization)和部分重同步(partial resynchronization)兩種模式:

  • 其中完整重同步用於處理初次複製情況:完整重同步的執行步驟和SYNC命令的執行步驟基本一樣,它們都是通過讓主伺服器建立並發送RDB檔案,以及向從伺服器發送儲存在緩衝區裡面的寫命令來進行同步;
  • 而部分重同步則用於處理斷線後重複製情況:當從伺服器在斷線後重新串連主伺服器時,如果條件允許,主伺服器可以將主從伺服器串連斷開期間執行的寫命令發送給從伺服器,從伺服器只要接收並執行這些寫命令,就可以將資料庫更新至主伺服器當前所處的狀態。

我們現在試舉一例來看看使用PSYNC處理斷線後情況:

展示了主從伺服器在執行部分重同步時的通訊過程。

其實看到這裡的時候心裡還是有一個疑問的:如果上面的例子是T3時候從伺服器掉線,然後在T10093的時候才串連上或者更長的時間呢!!!你這樣一條指令一條指令地傳輸過去還不如直接來一個SYNC命令快一些。所以在我看來使用PSYNC濟寧操作時,什麼時候部分重同步,什麼時候全部重同步是一個策略問題。當然Redis會解決這個問題,所以大家繼續看0_0

部分重同步的實現

部分重同步功能由以下三個部分構成:

  • 主伺服器的複製位移量(replication offset)和從伺服器的複製位移量;
  • 主伺服器的複製積壓緩衝區(replication backlog)
  • 伺服器的運行ID(run ID)。
複製位移量

執行複製的雙方——主伺服器和從伺服器會分別維護一個複製位移量:

  • 主伺服器每次向從伺服器傳播N個位元組的資料時,就將自己的複製位移量的值加上N;
  • 從伺服器每次收到主伺服器傳播來的N個位元組的資料時,就將自己的複製位移量的值加上N;

(我靠!!難道從伺服器沒有反饋嗎?丟包了怎麼辦?難道是用TCP?大家繼續看,我只是想穿插一些我的思路)

通過對比主從伺服器的複製位移量,程式可以很容易地知道主從伺服器是否處於一致狀態:

  • 如果主從伺服器處於一致狀態,那麼主從伺服器兩者的位移量總是相同的;
  • 相反,如果主從伺服器兩者的位移量並不相同,那麼說明主從伺服器並未處於一致狀態。

如下面的情況:

假設從伺服器A在斷線之後就立即重新串連主伺服器,並且成功,那麼接下來,從伺服器將向主伺服器發送PSYNC命令,報告從伺服器A當前的複製位移量為10086,那麼這時,主伺服器應該對從伺服器執行完整重同步還是部分重同步呢?如果執行部分重同步的話,主伺服器又如何補償從伺服器A在斷線期間丟失的那部分資料呢?以上問題的答案都和複製積壓緩衝區有關。

複製積壓緩衝區

複製積壓緩衝區是由主伺服器維護的一個固定長度(fixed-size)先進先出(FIFO)隊列,預設大小為1MB。

和普通先進先出隊列隨著元素的增加和減少而動態調整長度不同,固定長度先進先出隊列的長度是固定的,當入隊元素的數量大於隊列長度時,最先入隊的元素會被彈出,而新元素會被放入隊列。

當主伺服器進行命令傳播時,它不僅會將寫命令發送給所有從伺服器,還會將寫命令入隊到複製積壓緩衝區裡面,。

因此,主伺服器的複製積壓緩衝區裡面會儲存著一部分最近傳播的寫命令,並且複製積壓緩衝區會為隊列中的每個位元組記錄相應的複製位移量,就像下表所示的那樣。

當從伺服器重新連上主伺服器時,從伺服器會通過PSYNC命令將自己的複製位移量offset發送給主伺服器,主伺服器會根據這個複製位移量來決定對從伺服器執行何種同步操作:

  • 如果offset位移量之後的資料(也即是位移量offset+1開始的資料)仍然存在於複製積壓緩衝區裡面,那麼主伺服器將對從伺服器執行部分重同步操作;
  • 相反,如果offset位移量之後的資料已經不存在於複製積壓緩衝區,那麼主伺服器將對從伺服器執行完整重同步操作。
根據需要調整複製積壓緩衝區的大小

Redis為複製積壓緩衝區設定的預設大小為1MB,如果主伺服器需要執行大量寫命令,又或者主從伺服器斷線後重串連所需的時間比較長,那麼這個大小也許並不合適。如果複製積壓緩衝區的大小設定得不恰當,那麼PSYNC命令的複製重同步模式就不能正常發揮作用,因此,正確估算和設定複製積壓緩衝區的大小非常重要。
複製積壓緩衝區的最小大小可以根據公式second*write_size_per_second來估算:

  • 其中second為從伺服器斷線後重新串連上主伺服器所需的平均時間(以秒計算);
  • 而write_size_per_second則是主伺服器平均每秒產生的寫命令資料量(協議格式的寫命令的長度總和);

例如,如果主伺服器平均每秒產生1 MB的寫資料,而從伺服器斷線之後平均要5秒才能重新串連上主伺服器,那麼複製積壓緩衝區的大小就不能低於5MB。
為了安全起見,可以將複制積壓緩衝區的大小設為2*second*write_size_per_second,這樣可以保證絕大部分斷線情況都能用部分重同步來處理。
至於複製積壓緩衝區大小的修改方法,可以參考設定檔中關於repl-backlog-size選項的說明。

伺服器運行ID

除了複製位移量和複製積壓緩衝區之外,實現部分重同步還需要用到伺服器運行ID(run ID):

  • 每個Redis伺服器,不論主伺服器還是從服務,都會有自己的運行ID;
  • 運行ID在伺服器啟動時自動產生,由40個隨機的十六進位字元組成,例如53b9b28df8042fdc9ab5e3fcbbbabff1d5dce2b3;

當從伺服器對主伺服器進行初次複製時,主伺服器會將自己的運行ID傳送給從伺服器,而從伺服器則會將這個運行ID儲存起來。

當從伺服器斷線並重新連上一個主伺服器時,從伺服器將向當前串連的主伺服器發送之前儲存的運行ID:

  • 如果從伺服器儲存的運行ID和當前串連的主伺服器的運行ID相同,那麼說明從伺服器斷線之前複製的就是當前串連的這個主伺服器,主伺服器可以繼續嘗試執行部分重同步操作;
  • 相反地,如果從伺服器儲存的運行ID和當前串連的主伺服器的運行ID並不相同,那麼說明從伺服器斷線之前複製的主伺服器並不是當前串連的這個主伺服器,主伺服器將對從伺服器執行完整重同步操作。
PSYNC命令的實現

PSYNC命令的調用方法有兩種:

  • 如果從伺服器以前沒有複製過任何主伺服器,或者之前執行過SLAVEOF no one命令,那麼從伺服器在開始一次新的複製時將向主伺服器發送PSYNC ? -1命令,主動請求主伺服器進行完整重同步(因為這時不可能執行部分重同步);
  • 相反地,如果從伺服器已經複製過某個主伺服器,那麼從伺服器在開始一次新的複製時將向主伺服器發送PSYNC <runid> <offset>命令:其中runid是上一次複製的主伺服器的運行ID,而offset則是從伺服器當前的複製位移量,接收到這個命令的主伺服器會通過這兩個參數來判斷應該對從伺服器執行哪種同步操作。

根據情況,接收到PSYNC命令的主伺服器會向從伺服器返回以下三種回複的其中一種:

  • 如果主伺服器返回+FULLRESYNC <runid> <offset>回複,那麼表示主伺服器將與從伺服器執行完整重同步操作:其中runid是這個主伺服器的運行ID,從伺服器會將這個ID儲存起來,在下一次發送PSYNC命令時使用;而offset則是主伺服器當前的複製位移量,從伺服器會將這個值作為自己的初始化位移量;
  • 如果主伺服器返回+CONTINUE回複,那麼表示主伺服器將與從伺服器執行部分重同步操作,從伺服器只要等著主伺服器將自己缺少的那部分資料發送過來就可以了;
  • 如果主伺服器返回-ERR回複,那麼表示主伺服器的版本低於Redis 2.8,它識別不了PSYNC命令,從伺服器將向主伺服器發送SYNC命令,並與主伺服器執行完整同步操作。

 

redis學習筆記——主從同步(複製)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.