日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網(wǎng)站首頁 編程語言 正文

Redis的數(shù)據(jù)復制過程詳解_Redis

作者:真正的飛魚 ? 更新時間: 2023-01-26 編程語言

介紹 Redis 的復制

Redis 的復制功能分為同步(sync)和命令傳播(command propagate)這兩個操作

  • 同步操作用于,將從服務(wù)器的數(shù)據(jù)庫狀態(tài)更新至主服務(wù)器當前所處的數(shù)據(jù)庫狀態(tài);
  • 命令傳播操作用于,在主服務(wù)器的數(shù)據(jù)庫狀態(tài)被修改,導致主從服務(wù)器的數(shù)據(jù)庫狀態(tài)出現(xiàn)不一致時,讓主從服務(wù)器的數(shù)據(jù)庫重新回到一致狀態(tài)。

如果主從服務(wù)器雙方的數(shù)據(jù)庫保存相同的數(shù)據(jù),我們稱主從服務(wù)器的數(shù)據(jù)庫狀態(tài)一致

當從服務(wù)器第一次連接主服務(wù)器時,Redis 使用全量復制進行數(shù)據(jù)同步。

當從服務(wù)器在斷線后重新連接主服務(wù)器時,Redis 使用增量復制進行數(shù)據(jù)同步。

完整重同步

全量復制,也被稱為完整重同步。

當客戶端向從服務(wù)器發(fā)送 slaveof 命令,要求從服務(wù)器復制主服務(wù)器時,從服務(wù)器首先需要執(zhí)行同步操作,將從服務(wù)器的數(shù)據(jù)庫狀態(tài)更新至主服務(wù)器當前所處的數(shù)據(jù)庫狀態(tài)。

從服務(wù)器對主服務(wù)器的完整重同步操作,需要通過向主服務(wù)器發(fā)送 psync 命令來完成。psync 的命令為:psync ? -1

psync 命令在完整重同步模式下的的執(zhí)行步驟:讓主服務(wù)器創(chuàng)建并發(fā)送 RDB 文件,以及主服務(wù)器向從服務(wù)器發(fā)送保存在緩沖區(qū)里面的寫命令來進行同步。

  • 從服務(wù)器向主服務(wù)器發(fā)送 psync 命令。
  • 主服務(wù)器收到 psync 命令后,主服務(wù)器執(zhí)行 bgsave 命令,在后臺生成一個 RDB 文件,并使用一個緩沖區(qū)(replication buffer)記錄從現(xiàn)在開始執(zhí)行的所有寫命令。
  • 主服務(wù)器給從服務(wù)器同步數(shù)據(jù):當主服務(wù)器的 bgsave 命令執(zhí)行完畢時,主服務(wù)器會將 bgsave 命令生成的 RDB 文件發(fā)送給從服務(wù)器,從服務(wù)器接收并載入這個 RDB 文件,將自己的數(shù)據(jù)庫狀態(tài)更新至主服務(wù)器執(zhí)行 bgsave 命令時的數(shù)據(jù)庫狀態(tài)。
  • 主服務(wù)器給從服務(wù)器發(fā)送緩沖區(qū)里面的所有寫命令:主服務(wù)器將記錄在緩沖區(qū)里面的所有寫命令發(fā)送給從服務(wù)器, 從服務(wù)器執(zhí)行這些寫命令,將自己的數(shù)據(jù)庫狀態(tài)更新至主服務(wù)器數(shù)據(jù)庫當前所處的狀態(tài)。

需要注意的是:

從庫在開始和主庫進行數(shù)據(jù)復制前,可能保存了其他數(shù)據(jù)。為了避免之前數(shù)據(jù)的影響,從庫在收到主庫發(fā)送的 RDB 文件后,會先把自己當前的數(shù)據(jù)庫清空。

介紹 偏移量 & 積壓緩沖區(qū) & 運行ID

部分重同步功能通過以下三個部分來實現(xiàn):

  • 主服務(wù)器的復制偏移量 和 從服務(wù)器的復制偏移量(replication offset)
  • 主服務(wù)器的復制積壓緩沖區(qū)(replication backlog buffer)
  • 服務(wù)器的運行 ID(run ID)

復制偏移量

主服務(wù)器和從服務(wù)器會分別維護一個復制偏移量:

  • 主服務(wù)器每次向從服務(wù)器傳播 N 個字節(jié)的數(shù)據(jù)時,就將自己的復制偏移量的值加上 N。
  • 從服務(wù)器每次收到主服務(wù)器傳播來的 N 個字節(jié)的數(shù)據(jù)時,就將自己的復制偏移量的值加上 N。

通過對比主從服務(wù)器的復制偏移量,程序可以很容易地知道主從服務(wù)器是否處于一致狀態(tài):

  • 如果主從服務(wù)器兩者的偏移量總是相同,那么說明主從服務(wù)器處于一致狀態(tài)。
  • 如果主從服務(wù)器兩者的偏移量并不相同,那么說明主從服務(wù)器并未處于一致狀態(tài)。

復制積壓緩沖區(qū)

復制積壓緩沖區(qū)(repl_backlog_buffer)是由主服務(wù)器維護的一個固定長度的先進先出(FIFO)隊列。

固定指的是,當入隊元素的數(shù)量大于隊列長度時,最先入隊的元素會被彈出,而新元素會被放入隊列。或者理解復制積壓緩沖區(qū)為一個環(huán)形緩沖區(qū)。

當主服務(wù)器進行命令傳播時,它不僅會將寫命令發(fā)送給所有從服務(wù)器,還會將寫命令入隊到復制積壓緩沖區(qū)里面。

因此,主服務(wù)器的復制積壓緩沖區(qū)里面會保存著一部分最近傳播的寫命令,并且復制積壓緩沖區(qū)會為隊列中的每個字節(jié)記錄相應(yīng)的復制偏移量。

當從服務(wù)器在斷線后重新連接主服務(wù)器時,從服務(wù)器會通過 psync 命令將自己的復制偏移量 offset 發(fā)送給主服務(wù)器,主服務(wù)器會根據(jù)這個復制偏移量來決定對從服務(wù)器執(zhí)行完整重同步還是部分重同步操作:

  • 如果 offset 偏移量之后的數(shù)據(jù)(也即是偏移量 offset+1 開始的數(shù)據(jù))仍然存在于復制積壓緩沖區(qū)里面,那么主服務(wù)器將對從服務(wù)器執(zhí)行部分重同步操作。
  • 如果 offset 偏移量之后的數(shù)據(jù)已經(jīng)不存在于復制積壓緩沖區(qū),那么主服務(wù)器將對從服務(wù)器執(zhí)行完整重同步操作。

復制積壓緩沖區(qū)的大小

Redis 為復制積壓緩沖區(qū)設(shè)置的默認大小為 1MB,如果主服務(wù)器需要執(zhí)行大量的寫命令,又或者主從服務(wù)器斷線后重連接所需的時間比較長,那么這個大小也許并不合適。我們可以通過 repl-backlog-size 選項修改復制積壓緩沖區(qū)的大小。

如果復制積壓緩沖區(qū)的大小設(shè)置得不恰當,那么 psync 命令的部分重同步復制就不能正常發(fā)揮作用。因此,正確估算和設(shè)置復制積壓緩沖區(qū)的大小非常重要。

為了保證主從服務(wù)器斷線并重連接后可以使用部分重同步功能,我們需要保證復制積壓緩沖區(qū)的大小足夠大。復制積壓緩沖區(qū)的最小大小可以根據(jù)公式 second * write_size_per_second 來估算:

  • second 是從服務(wù)器斷線后重新連接上主服務(wù)器所需的平均時間(以秒計算)。
  • write_size_per_second 是主服務(wù)器平均每秒產(chǎn)生的寫命令數(shù)據(jù)量(協(xié)議格式的寫命令的長度總和)。

例如,如果主服務(wù)器平均每秒產(chǎn)生1 MB的寫數(shù)據(jù),而從服務(wù)器斷線之后平均要 5 秒才能重新連接上主服務(wù)器,那么復制積壓緩沖區(qū)的大小就不能低于 5 MB。

為了安全起見,可以將復制積壓緩沖區(qū)的大小設(shè)為: 2 * second * write_size_per_second,這樣可以保證絕大部分斷線情況都能用部分重同步來處理。

服務(wù)器運行 ID

每個 Redis 服務(wù)器,不論主服務(wù)器還是從服務(wù),都會有自己的運行 ID。運行 ID 在服務(wù)器啟動時自動生成,由 40 個隨機的十六進制字符組成,例如:53b9b28df8042fdc9ab5e3fcbbbabff1d5dce2b3。

當從服務(wù)器對主服務(wù)器進行初次復制時,主服務(wù)器會將自己的運行 ID 發(fā)送給從服務(wù)器,而從服務(wù)器會將主服務(wù)器的這個運行 ID 保存起來。 當從服務(wù)器斷線并重新連上一個主服務(wù)器時,從服務(wù)器將向當前連接的主服務(wù)器發(fā)送之前保存的主服務(wù)器的運行 ID:

  • 如果從服務(wù)器保存的主服務(wù)器的運行 ID 和當前連接的主服務(wù)器的運行 ID 相同,那么說明從服務(wù)器斷線之前復制的就是當前連接的這個主服務(wù)器, 主服務(wù)器可以繼續(xù)嘗試執(zhí)行部分重同步操作。
  • 如果從服務(wù)器保存的主服務(wù)器的運行 ID 和當前連接的主服務(wù)器的運行 ID 并不相同,那么說明從服務(wù)器斷線之前復制的主服務(wù)器并不是當前連接的這個主服務(wù)器,主服務(wù)器將對從服務(wù)器執(zhí)行完整重同步操作。

部分重同步

增量復制,也被稱為部分重同步。

在 Redis 中,從庫對主庫的復制可以分為以下兩種情況:

  • 初次復制:從庫以前沒有復制過任何主庫,或者從庫當前要復制的主服務(wù)器和上一次復制的主服務(wù)器不同。
  • 網(wǎng)絡(luò)斷線重連后復制:處于命令傳播階段的主從庫因為網(wǎng)絡(luò)原因而中斷了復制,但從庫通過自動重連接重新連上了主庫,并繼續(xù)復制主服。

在 Redis 2.8 之前,如果主從庫在命令傳播時出現(xiàn)了網(wǎng)絡(luò)中斷,那么在斷線重連后,從庫會和主庫重新進行一次全量復制,開銷非常大。

從 2.8 版本開始,Redis 引入了部分重同步功能。部分重同步指的是,從服務(wù)器只同步主服務(wù)器的部分數(shù)據(jù)。當從服務(wù)器在斷線后重新連接主服務(wù)器時,如果條件允許,主服務(wù)器可以將主從服務(wù)器連接斷開期間執(zhí)行的寫命令發(fā)送給從服務(wù)器,從服務(wù)器只要接收并執(zhí)行這些寫命令,就可以將數(shù)據(jù)庫更新至主服務(wù)器當前所處的狀態(tài)。

執(zhí)行部分重同步是有前提條件的。

  • offset 偏移量
  • 運行 ID

當從服務(wù)器對主服務(wù)器進行初次復制時,主服務(wù)器會將自己的運行 ID 發(fā)送給從服務(wù)器,而從服務(wù)器會將主服務(wù)器的這個運行 ID 保存起來。 當從服務(wù)器斷線并重新連上一個主服務(wù)器時,從服務(wù)器會通過 psync 命令將自己的復制偏移量 offset 和 之前保存的主服務(wù)器的運行 ID 發(fā)送給主服務(wù)器。

主服務(wù)器會根據(jù)這個復制偏移量 和 運行ID 來決定對從服務(wù)器執(zhí)行完整重同步還是部分重同步操作:

  • 如果從服務(wù)器保存的主服務(wù)器的運行 ID 和當前連接的主服務(wù)器的運行 ID 相同,那么說明從服務(wù)器斷線之前復制的就是當前連接的這個主服務(wù)器, 主服務(wù)器可以繼續(xù)嘗試執(zhí)行部分重同步操作。
  • 如果從服務(wù)器保存的主服務(wù)器的運行 ID 和當前連接的主服務(wù)器的運行 ID 并不相同,那么說明從服務(wù)器斷線之前復制的主服務(wù)器并不是當前連接的這個主服務(wù)器,主服務(wù)器將對從服務(wù)器執(zhí)行完整重同步操作。
  • 如果 offset 偏移量之后的數(shù)據(jù)(也即是偏移量 offset+1 開始的數(shù)據(jù))仍然存在于復制積壓緩沖區(qū)里面,那么主服務(wù)器將對從服務(wù)器執(zhí)行部分重同步操作。
  • 如果 offset 偏移量之后的數(shù)據(jù)已經(jīng)不存在于復制積壓緩沖區(qū),那么主服務(wù)器將對從服務(wù)器執(zhí)行完整重同步操作。

從服務(wù)器對主服務(wù)器的部分重同步操作,需要通過向主服務(wù)器發(fā)送 psync 命令來完成。psync 命令為:psync < runID > < offset >

psync 命令

從服務(wù)器對主服務(wù)器的同步操作,需要通過向主服務(wù)器發(fā)送 psync 命令來完成。

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

  • 完整重同步用于,處理初次復制情況;
  • 部分重同步用于,處理斷線后重復制情況:當從服務(wù)器在斷線后重新連接主服務(wù)器時,如果條件允許,主服務(wù)器可以將主從服務(wù)器連 接斷開期間執(zhí)行的寫命令發(fā)送給從服務(wù)器,從服務(wù)器只要接收并執(zhí)行這 些寫命令,就可以將數(shù)據(jù)庫更新至主服務(wù)器當前所處的狀態(tài)。

psync 命令的調(diào)用方法有兩種:

  • 如果從服務(wù)器以前沒有復制過任何主服務(wù)器,或者之前執(zhí)行過 slaveof no one 命令,那么從服務(wù)器在開始一次新的復制時將向主服務(wù)器發(fā)送 psync ? -1 命令,主動請求主服務(wù)器進行完整重同步。
  • 如果從服務(wù)器已經(jīng)復制過某個主服務(wù)器,那么從服務(wù)器在開始一次新的復制時將向主服務(wù)器發(fā)送 psync?命令:其中 runid 是上一次復制的主服務(wù)器的運行 ID,而 offset 則是從服務(wù)器當前的復制偏移量,接收到這個命令的主服務(wù)器會通過這兩個參數(shù)來判斷應(yīng)該對從服務(wù)器執(zhí)行哪種同步操作。

根據(jù)情況,接收到 psync 命令的主服務(wù)器會向從服務(wù)器返回以下三種回復的其中一種:

  • 如果主服務(wù)器返回 +fullresync?回復,那么表示主服務(wù)器將與從服務(wù)器執(zhí)行完整重同步操作:其中 runid 是這個主服務(wù)器的運行 ID,從服務(wù)器會將這個 ID 保存起來,在下一次發(fā)送 psync 命令時使用;而 offset 則是主服務(wù)器當前的復制偏移量,從服務(wù)器會將這個值作為自己的初始化偏移量。
  • 如果主服務(wù)器返回 +continue 回復,那么表示主服務(wù)器將與從服務(wù)器執(zhí)行部分重同步操作,從服務(wù)器只要等著主服務(wù)器將自己缺少的那部分數(shù)據(jù)發(fā)送過來就可以了。
  • 如果主服務(wù)器返回 -err 回復,那么表示主服務(wù)器的版本低于 Redis2.8,它識別不了 psync 命令,從服務(wù)器將向主服務(wù)器發(fā)送 sync 命令,并與主服務(wù)器執(zhí)行完整同步操作。

命令傳播

主服務(wù)器通過向從服務(wù)器傳播命令來更新從服務(wù)器的狀態(tài),保持主從服務(wù)器一致。

當完成了同步之后, 主從服務(wù)器就會進入命令傳播階段, 這時主服務(wù)器只要一直將自己執(zhí)行的寫命令發(fā)送給從服務(wù)器, 而從服務(wù)器只要一直接收并執(zhí)行主服務(wù)器發(fā)來的寫命令, 就可以保證主從服務(wù)器一直保持一致了。

主服務(wù)器進行命令傳播時,它不僅會將寫命令發(fā)送給所有從服務(wù)器,還會將寫命令入隊到復制積壓緩沖區(qū)里面。

心跳檢測

從服務(wù)器通過向主服務(wù)器發(fā)送命令來進行心跳檢測,以及命令丟失檢測。

在命令傳播階段,從服務(wù)器默認會以每秒一次的頻率,向主服務(wù)器發(fā)送命令:replconf ack <replication_offset>。其中 replication_offset 是從服務(wù)器當前的復制偏移量。

發(fā)送 replconf ack 命令對于主從服務(wù)器有三個作用:

  • 檢測主從服務(wù)器的網(wǎng)絡(luò)連接狀態(tài)。
  • 輔助實現(xiàn) min-slaves 選項。
  • 檢測命令丟失。

檢測主從服務(wù)器的網(wǎng)絡(luò)連接狀態(tài)。

主從服務(wù)器可以通過發(fā)送和接收 replconf ack 命令來檢查兩者之間的網(wǎng)絡(luò)連接是否正常:如果主服務(wù)器超過一秒鐘沒有收到從服務(wù)器發(fā)來的 replconf ack 命令,那么主服務(wù)器就知道主從服務(wù)器之間的連接出現(xiàn)問題了。

通過向主服務(wù)器發(fā)送 info replication 命令,在列出的從服務(wù)器列表的 lag 一欄中,我們可以看到相應(yīng)從服務(wù)器最后一次向主服務(wù)器發(fā)送 replconf ack 命令距離現(xiàn)在過了多少秒。在一般情況下,lag 的值應(yīng)該在 0 秒或者 1 秒之間跳動,如果超過 1 秒的話,那么說明主從服務(wù)器之間的連接出現(xiàn)了故障。

輔助實現(xiàn) min-slaves 選項。

Redis 的 min-slaves-to-write 和 min-slaves-max-lag 兩個選項可以防止主服務(wù)器在不安全的情況下執(zhí)行寫命令。

舉個例子,如果我們向主服務(wù)器提供以下設(shè)置:

  • min-slaves-to-write 3
  • min-slaves-max-lag 10

那么在從服務(wù)器的數(shù)量少于 3 個,或者 3 個從服務(wù)器的延遲(lag)值都 ≥ 10 秒時,主服務(wù)器將拒絕執(zhí)行寫命令,這里的延遲值就是上面提到的 info replication 命令的 lag 值。

檢測命令丟失。

如果因為網(wǎng)絡(luò)故障,主服務(wù)器傳播給從服務(wù)器的寫命令在半路丟失,那么當從服務(wù)器向主服務(wù)器發(fā)送 replconf ack 命令時,主服務(wù)器將發(fā)覺從服務(wù)器當前的復制偏移量少于自己的復制偏移量,然后主服務(wù)器就會根據(jù)從服務(wù)器提交的復制偏移量,在復制積壓緩沖區(qū)里面找到從服務(wù)器缺少的數(shù)據(jù),并將這些數(shù)據(jù)重新發(fā)送給從服務(wù)器。

參考資料

《Redis設(shè)計與實現(xiàn)》

原文鏈接:https://www.cnblogs.com/feiyu2/p/16996233.html

欄目分類
最近更新