天天看點

Redis主從複制原理及過期key處理(上)1 依賴機制2 Redis 複制特點1 單機“危機”2 實作複制的操作3 全量複制(全量同步)

在Redis複制的基礎上(不包括Redis Cluster或Redis Sentinel作為附加層提供的高可用功能),使用和配置主從複制非常簡單,能使得 【Redis從伺服器】(下文稱R)能精确得複制 【Redis主伺服器】(下文稱M)的内容。

每當 R 和 M 之間的連接配接斷開時, R 會自動重連到 M,并且無論這期間 M 發生了什麼, R 都将嘗試讓自身成為 M 的精确副本。

1 依賴機制

該系統的運作依靠如下重要的機制:

1.1 更新 R

當一個 M 和一個 R 連接配接正常時, M 會發送一連串指令流保持對 R 的更新,以便将自身資料集的改變複制給 R,這包括用戶端的寫入、key 的過期或被逐出等

1.2 部分重同步

M、R 斷連後,因為網絡問題或主從意識到連接配接逾時, R 重新連接配接上 M 并會嘗試進行部分重同步:它會嘗試隻擷取在斷開連接配接期間内丢失的指令流。

1.3 全量重同步

當無法進行部分重同步時, R 會請求全量重同步。

這涉及到一個更複雜過程,比如M需建立所有資料的快照,将之發送給 R ,之後在資料集更改時持續發送指令流到 R。

Redis使用預設的異步複制,低延遲且高性能,适用于大多數 Redis 場景。但R會異步确認其從M周期接收到的資料量。

用戶端可使用 WAIT 指令請求同步複制某些特定的資料。但WAIT指令隻能確定在其他 Redis 執行個體中有指定數量的已确認的副本:在故障轉移期間,由于不同原因的故障轉移或是由于 Redis 持久性的實際配置,故障轉移期間确認的寫入操作可能仍然會丢失。

2 Redis 複制特點

  • Redis 使用異步複制,R 和 M 之間異步地确認處理的資料量
  • 一個 M 可有多個 R
  • R 可接受其他 R 的連接配接

    除了多個 R 可以連接配接到同一 M,R 間也可以像層級連接配接其它 R。Redis 4.0起,所有 sub-R 将會從 M 收到完全一樣的複制流

  • Redis 複制在 M 側是非阻塞的

    M 在一或多 R 進行初次同步或者是部分重同步時,可以繼續處理查詢請求

  • 複制在 R 側大部分也是非阻塞當 R 進行初次同步時,它可以使用舊資料集處理查詢請求,假設在 redis.conf 中配置了讓 Redis 這樣做。否則,你可以配置如果複制流斷開, Redis R 會傳回一個 error 給用戶端。但在初次同步後,舊資料集必須被删除,同時加載新的資料集。 R 在這個短暫的時間視窗内(如果資料集很大,會持續較長時間),會阻塞到來的連接配接請求。自 Redis 4.0 開始,可以配置 Redis 使删除舊資料集的操作在另一個不同的線程中進行,但是,加載新資料集的操作依然需要在主線程中進行并且會阻塞 R
  • 複制可被用在可伸縮性,以便隻讀查詢可以有多個 R 進行(例如 O(N) 複雜度的慢操作可以被下放到 R ),或者僅用于資料安全和高可用
  • 可使用複制來避免 M 将全部資料集寫入磁盤造成的開銷:一種典型的技術是配置你的 M 的 redis.conf以避免對磁盤進行持久化,然後連接配接一個 R ,配置為不定期儲存或是啟用 AOF。但是,這個設定必須小心處理,因為重新開機的 M 将從一個空資料集開始:如果一個 R 試圖與它同步,那麼這個 R 也會被清空!

1 單機“危機”

  • 容量瓶頸
  • 機器故障
  • QPS瓶頸
  • Redis主從複制原理及過期key處理(上)1 依賴機制2 Redis 複制特點1 單機“危機”2 實作複制的操作3 全量複制(全量同步)
  • 一主多從
  • Redis主從複制原理及過期key處理(上)1 依賴機制2 Redis 複制特點1 單機“危機”2 實作複制的操作3 全量複制(全量同步)

主從複制作用

  • 資料副本
  • 擴充讀性能
  1. 一個M可以有多個R
  2. 一個R隻能有一個M
  3. 資料流向是單向的,M => R

2 實作複制的操作

2.1 指令:Rof

異步執行,很耗時間

Redis主從複制原理及過期key處理(上)1 依賴機制2 Redis 複制特點1 單機“危機”2 實作複制的操作3 全量複制(全量同步)

無需重新開機,但是不便于配置管理。

2.2 配置

Rof ip port
R-read-only yes      

雖然可統一配置,但需重新開機。

3 全量複制(全量同步)

  1. M執行

    bgsave

    ,在本地生成一份RDB
    Redis主從複制原理及過期key處理(上)1 依賴機制2 Redis 複制特點1 單機“危機”2 實作複制的操作3 全量複制(全量同步)
  2. M将RDB發給salve,若RDB複制時間>60s(repl-timeout)
Redis主從複制原理及過期key處理(上)1 依賴機制2 Redis 複制特點1 單機“危機”2 實作複制的操作3 全量複制(全量同步)

則replica就會認為複制失敗,可适當調大該參數(對于千兆網卡的機器,一般每秒傳輸100MB,6G檔案,很可能超過60s)

Redis主從複制原理及過期key處理(上)1 依賴機制2 Redis 複制特點1 單機“危機”2 實作複制的操作3 全量複制(全量同步)

M在生成RDB時,會将所有新的寫指令緩存在記憶體中,在salve儲存了rdb之後,再将新的寫指令複制給salve

若在複制期間,記憶體緩沖區持續消耗超過64MB,或者一次性超過256MB,則停止複制,複制失敗

R node接收到RDB之後,清空自己的舊資料,然後重新加載RDB到自己的記憶體中,同時基于舊的資料版本對外提供服務

如果R開啟了AOF,那麼會立即執行BGREWRITEAOF,重寫AOF

Redis主從複制原理及過期key處理(上)1 依賴機制2 Redis 複制特點1 單機“危機”2 實作複制的操作3 全量複制(全量同步)

RDB生成、RDB通過網絡拷貝、R舊資料的清理、R aof rewrite,很耗費時間。

如果複制的資料量在4G~6G之間,那麼很可能全量複制時間消耗到1分半到2分鐘。

3.1 開銷

  1. bgsave時間
  2. RDB檔案網絡傳輸時間
  3. 從節點清空資料時間
  4. 從節點加載RDB的時間
  5. 可能的AOF重寫時間

3.2 細節

M 開啟一個背景save程序,以便生成一個 RDB 檔案。同時它開始緩沖所有從用戶端接收到的新的寫入指令。當背景save完成RDB檔案時, M 将該RDB資料集檔案發給 R, R會先将其寫入磁盤,然後再從磁盤加載到記憶體。再然後 M 會發送所有緩存的寫指令發給 R。這個過程以指令流的形式完成并且和 Redis 協定本身的格式相同。

當主從之間的連接配接因為一些原因崩潰之後, R 能夠自動重連。如果 M 收到了多個 R 要求同步的請求,它會執行一個單獨的背景儲存,以便于為多個 R 服務。

加速複制

預設情況下,M接收SYNC指令後執行BGSAVE,将資料先儲存到磁盤,若磁盤性能差,則寫入磁盤會消耗大量性能。

是以在Redis 2.8.18時進行改進,可以設定無需寫入磁盤直接發生RDB快照給R,加快複制速度。

複制SYNC政策:磁盤或套接字。僅僅接受差異就無法繼續複制過程的新副本和重新連接配接副本需要進行所謂的“完全同步”。 RDB檔案從主資料庫傳輸到副本資料庫。傳輸可以通過兩種不同的方式進行:1)支援磁盤:Redis主伺服器建立一個新過程,将RDB檔案寫入磁盤。後來,該檔案由父程序逐漸傳輸到副本。 2)無盤:Redis主伺服器建立一個新程序,該程序将RDB檔案直接寫入副本套接字,而完全不接觸磁盤。使用磁盤支援的複制,在生成RDB檔案的同時,隻要生成RDB檔案的目前子級完成工作,就可以将更多副本排入隊列并與RDB檔案一起使用。如果使用無盤複制,則一旦傳輸開始,新的副本将排隊,并且當目前副本終止時将開始新的傳輸。當使用無盤複制時,主伺服器在開始傳輸之前等待一段可配置的時間(以秒為機關),以希望多個副本可以到達并且傳輸可以并行化。使用慢速磁盤和快速(大帶寬)網絡時,無盤複制效果更好。

修改配置:

repl-diskless-sync yes (預設no)