面試官:請講一下Redis主從復制的功能及實現原理


摘要:Redis在主從模式下會有許多問題需要考慮,這里寫了一些關於redis在多服務器下的一些問題分析和總結。

Redis單節點存在單點故障問題,為了解決單點問題,一般都需要對redis配置從節點,然后使用哨兵來監聽主節點的存活狀態,如果主節點掛掉,從節點能繼續提供緩存功能。主從配置結合哨兵模式能解決單點故障問題,提高redis可用性。從節點僅提供讀操作,主節點提供寫操作。對於讀多寫少的狀況,可給主節點配置多個從節點,從而提高響應效率。

主從復制過程:

  • 從節點執行slaveof[masterIP][masterPort],保存主節點信息
  • 從節點中的定時任務發現主節點信息,建立和主節點的socket連接
  • 從節點發送Ping信號,主節點返回Pong,兩邊能互相通信
  • 連接建立后,主節點將所有數據發送給從節點(數據同步)
  • 主節點把當前的數據同步給從節點后,便完成了復制的建立過程。接下來,主節點就會持續的把寫命令發送給從節點,保證主從數據一致性。

Redis的數據同步過程:

redis2.8之前使用sync[runId][offset]同步命令,redis2.8之后使用psync[runId][offset]命令。

兩者不同在於,sync命令僅支持全量復制過程,psync支持全量和部分復制。

介紹同步之前,先介紹幾個概念:

runId:每個redis節點啟動都會生成唯一的uuid,每次redis重啟后,runId都會發生變化。

offset:主節點和從節點都各自維護自己的主從復制偏移量offset,當主節點有寫入命令時,offset=offset+命令的字節長度。從節點在收到主節點發送的命令后,也會增加自己的offset,並把自己的offset發送給主節點。這樣,主節點同時保存自己的offset和從節點的offset,通過對比offset來判斷主從節點數據是否一致。

repl_backlog_size:保存在主節點上的一個固定長度的先進先出隊列,默認大小是1MB。

  • 主節點發送數據給從節點過程中,主節點還會進行一些寫操作,這時候的數據存儲在復制緩沖區中。從節點同步主節點數據完成后,主節點將緩沖區的數據繼續發送給從節點,用於部分復制。
  • 主節點響應寫命令時,不但會把命名發送給從節點,還會寫入復制積壓緩沖區,用於復制命令丟失的數據補救。

上面是psync的執行流程:

從節點發送psync[runId][offset]命令,主節點有三種響應:

  • FULLRESYNC:第一次連接,進行全量復制
  • CONTINUE:進行部分復制
  • ERR:不支持psync命令,進行全量復制

全量復制和部分復制的過程

上面是全量復制的流程。主要有以下幾步:

  • 從節點發送psync ? -1命令(因為第一次發送,不知道主節點的runId,所以為?,因為是第一次復制,所以offset=-1)。
  • 主節點發現從節點是第一次復制,返回FULLRESYNC {runId} {offset},runId是主節點的runId,offset是主節點目前的offset。
  • 從節點接收主節點信息后,保存到info中。
  • 主節點在發送FULLRESYNC后,啟動bgsave命令,生成RDB文件(數據持久化)。
  • 主節點發送RDB文件給從節點。到從節點加載數據完成這段期間主節點的寫命令放入緩沖區。
  • 從節點清理自己的數據庫數據。
  • 從節點加載RDB文件,將數據保存到自己的數據庫中。-如果從節點開啟了AOF,從節點會異步重寫AOF文件。

關於部分復制有以下幾點說明:

  1. 部分復制主要是Redis針對全量復制的過高開銷做出的一種優化措施,使用psync[runId][offset]命令實現。當從節點正在復制主節點時,如果出現網絡閃斷或者命令丟失等異常情況時,從節點會向主節點要求補發丟失的命令數據,主節點的復制積壓緩沖區將這部分數據直接發送給從節點,這樣就可以保持主從節點復制的一致性。補發的這部分數據一般遠遠小於全量數據。
  2. 主從連接中斷期間主節點依然響應命令,但因復制連接中斷命令無法發送給從節點,不過主節點內的復制積壓緩沖區依然可以保存最近一段時間的寫命令數據。
  3. 當主從連接恢復后,由於從節點之前保存了自身已復制的偏移量和主節點的運行ID。因此會把它們當做psync參數發送給主節點,要求進行部分復制。
  4. 主節點接收到psync命令后首先核對參數runId是否與自身一致,如果一致,說明之前復制的是當前主節點;之后根據參數offset在復制積壓緩沖區中查找,如果offset之后的數據存在,則對從節點發送+COUTINUE命令,表示可以進行部分復制。因為緩沖區大小固定,若發生緩沖溢出,則進行全量復制。
  5. 主節點根據偏移量把復制積壓緩沖區里的數據發送給從節點,保證主從復制進入正常狀態。

Redis主從復制會存在以下問題:

  • 一旦主節點宕機,從節點晉升為主節點,同時需要修改應用方的主節點地址,還需要命令所有從節點去復制新的主節點,整個過程需要人工干預。
  • 主節點的寫能力受到單機的限制。
  • 主節點的存儲能力受到單機的限制。
  • 原生復制的弊端在早期的版本中也會比較突出,比如:redis復制中斷后,從節點會發起psync。此時如果同步不成功,則會進行全量同步,主庫執行全量備份的同時,可能會造成毫秒或秒級的卡頓。

所以用哨兵解決以上問題。

哨兵的功能

Redis Sentinel(哨兵)主要功能包括主節點存活檢測、主從運行情況檢測、自動故障轉移、主從切換。Redis Sentinel最小配置是一主一從。

Redis的Sentinel系統可以用來管理多個Redis服務器,該系統可以執行以下四個任務:

  • 監控:不斷檢查主服務器和從服務器是否正常運行。
  • 通知:當被監控的某個redis服務器出現問題,Sentinel通過API腳本向管理員或者其他應用程序發出通知。
  • 自動故障轉移:當主節點不能正常工作時,Sentinel會開始一次自動的故障轉移操作,它會將與失效主節點是主從關系的其中一個從節點升級為新的主節點,並且將其他的從節點指向新的主節點,這樣人工干預就可以免了。
  • 配置提供者:在Redis Sentinel模式下,客戶端應用在初始化時連接的是Sentinel節點集合,從中獲取主節點的信息。

哨兵的原理

1、每個Sentinel節點都需要定期執行以下任務:每個Sentinel以每秒一次的頻率,向它所知的主服務器、從服務器以及其他的Sentinel實例發送一個PING命令。(如上圖)

2、如果一個實例距離最后一次有效回復PING命令的時間超過down-after-milliseconds所指定的值,那么這個實例會被Sentinel標記為主觀下線。(如上圖)

3、如果一個主服務器被標記為主觀下線,那么正在監視這個服務器的所有Sentinel節點,要以每秒一次的頻率確認主服務器的確進入了主觀下線狀態。

4、如果一個主服務器被標記為主觀下線,並且有足夠數量的Sentinel(至少要達到配置文件指定的數量)在指定的時間范圍內同意這一判斷,那么這個主服務器被標記為客觀下線。

5、一般情況下,每個Sentinel會以每10秒一次的頻率向它已知的所有主服務器和從服務器發送INFO命令,當一個主服務器被標記為客觀下線時,Sentinel向下線主服務器的所有從服務器發送INFO命令的頻率,會從10秒一次改為每秒一次。

6、Sentinel和其他Sentinel協商客觀下線的主節點的狀態,如果處於SDOWN狀態,則投票自動選出新的主節點,將剩余從節點指向新的主節點進行數據復制。

7、當沒有足夠數量的Sentinel同意主服務器下線時,主服務器的客觀下線狀態就會被移除。當主服務器重新向Sentinel的PING命令返回有效回復時,主服務器的主觀下線狀態就會被移除。

 

點擊關注,第一時間了解華為雲新鮮技術~


免責聲明!

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



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