Redis基礎篇(六)數據同步:主從復制


Redis具有高可靠性,體現在兩方面:

  • 一是數據盡量少丟失,通過前面介紹的持久化方式AOF和RDB,在宕機時可以恢復數據。
  • 二是服務盡量少中斷,通過副本冗余來實現。

今天我們學習的就是通過主從復制實現副本冗余,從而實現Redis的高可靠性。

什么是主從復制

Redis提供主從庫模式,保證數據副本的一致,主從庫之間采用的是讀寫分離的方式。

為什么要讀寫分離?

如果允許所有節點能夠處理讀寫請求,就需要解決加鎖、實例間協商、數據同步等操作,會帶來巨額的開銷。

因此采用主從庫模式時,要配置主庫只寫,從庫只讀。

主從庫如何進行第一次同步?

當設置了主從庫模式,此時從庫是空的,如何進行主從庫的第一次同步呢?

Redis采用全量復制來進行第一次同步,具體有三個步驟,如下圖所示:

image

第一步,主從庫建立連接,協商同步。

  1. 從庫發送psync命令,表示進行數據同步。其中runID表示主庫ID,第一次不知道主庫的runID,就設置為"?"
  2. 主庫收到psync命令后,用FULLRESYNC響應,返回runID(主庫ID)和offset(主庫目前的復制進度)。
  3. 從庫收到響應后,記錄這兩個參數

第二步:主庫同步數據給從庫。

從庫收到數據后,在本地完成數據加載。這過程依賴於RDB快照。

  1. 主庫執行bgsave命令,生成RDB文件,再把文件發強從庫。
  2. 從庫收到RDB文件后,先清空當前數據庫,然后加載RDB文件。

第三步,主庫發送新寫命令給從庫

主庫在數據同步過程中,會記錄所有寫操作,避免丟失同步過程接收的新的寫命令。

  1. 主庫使用replication buffer來新的寫命令。
  2. 當從庫加載RDB文件完成后,主庫再把replication buffer的內容發送給從庫,從庫再執行這些操作實現同步。

關於replication buffer的更多內容,下面再介紹。

如果有多個從庫,每個從庫都要跟主庫進行全量同步,這樣主庫的壓力會很大。

主從級聯模式

Redis提供“主-從-從”模式將主庫生成RDB和傳輸RDB的壓力,以級聯的方式分散到從庫上。

簡單來說,構建父子從庫結構,子從庫的數據同步從父從庫獲取。如下圖所示:

image

在從庫上執行命令:replicaof 所選從庫的IP 6379,就可以設置從庫的父從庫了。

至此,主從庫完成了第一次同步,那后續如何保持同步呢?

如何保持同步?

當主從庫完成同步后,會維護一個網絡連接,主庫會通過這個連接將后續的命令同步給從庫。

但是這里有潛在的風險點:如果網絡斷連或者出現阻塞了,那怎么辦呢?

主從庫間網絡斷了怎么辦?

在Redis 2.8之前,網絡斷了后要重新進行全量復制。但在Redis 2.8之后,Redis提供了增量復制的方式。

當建立了主從結構后,主庫會把寫命令寫入repl_backlog_buffer緩沖區里,當網絡斷開並重新連接后,從庫會發送同步命令,然后主庫再把未同步的命令發送給從庫,從庫執行這些命令就恢復數據一致了。具體流程如下圖所示:

增量復制流程

repl_backlog_buffer是一個環形緩沖區,如下圖所示:

image

由於其環形結構,當因為網絡問題影響從庫讀取命令的速度,會出現寫滿后繼續寫入命令時,會覆蓋掉從庫還沒讀的內容,從而造成數據不一致,需要重新全量復制。

因此要根據情況來設置repl_backlog_buffer的大小,通過配置repl_backlog_size來調整緩沖區大小。配置公式為:緩沖空間大小 = 主庫寫入命令速度 * 操作大小 - 主從庫間網絡傳輸命令速度 * 操作大小。而repl_backlog_size= 緩沖空間 * 2

例如主庫寫操作2000/秒,每個操作大小2KB,網絡傳輸1000個操作/秒,那緩沖空間大小=2000*2 - 1000*2=2MB,那repl_backlog_size就設置為4MB。

拓展

為什么主庫間的數據復制同步不使用AOF?

有三方面原因:

  1. RDB文件是經過二進制壓縮的,文件很小,這樣主從庫間傳輸就很快。
  2. 從庫加載RDB文件速度很快,而AOF日志還要逐行命令執行,速度很慢。
  3. 假設使用AOF,那就必須打開AOF,Redis默認是不開啟AOF的,可能會影響Redis性能。

關於replication buffer

每個與Redis通信的客戶端(從庫也算client),都會分配一個buffer,所有數據交互都是通過這個buffer進行的。

Redis先把數據寫到這個buffer中,然后再把buffer中的數據發到client的socket中,通過網絡發送出去,完成數據交互。

而主從同步的這個buffer,是用於保證主從數據一致的,所以才叫它replication buffer。

可以通過配置項client-output-buffer-limit來配置這個buffer的大小。當保存到buffer里的內容超過限制,主庫會強制斷開這個client的連接。這樣會有潛在風險。

如果從庫處理主庫傳輸的命令非常慢,就會把這個buffer撐滿,然后主庫會斷開連接。中斷后,從庫再次發起復制請求,可能會導致惡性循環,引發復制風暴。

小結

  • 主從庫模式是采用RDB快照的全量復制 + 基於長連接的網絡通信實現主從復制的。
  • 通過“主-從-從”模式,將主庫生成RDB和傳輸RDB的壓力,以級聯的方式分散到從庫上。
  • 當網絡中斷,通過主庫的repl_backlog_buffer,實現增量復制,無須重新全量復制。
  • repl_backlog_buffer是環形緩沖區,要根據網絡狀況,合理配置其大小。
  • 一個Redis實例的數據庫不要太大,在幾GB比較合適,這樣可以減少RDB文件生成、傳輸和重新加載的開銷。

參考資料


免責聲明!

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



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