12.26 分佈式系統之Redis主從架構

單機的 redis,能夠承載的 QPS 大概就在上萬到幾萬不等。對於緩存來說,一般都是用來支撐

讀高併發的。因此架構做成主從(master-slave)架構,一主多從,主負責寫,並且將數據複製到其它的 slave 節點,從節點負責讀。所有的讀請求全部走從節點。這樣也可以很輕鬆實現水平擴容,支撐讀高併發

分佈式系統之Redis主從架構

redis replication -> 主從架構 -> 讀寫分離 -> 水平擴容支撐讀高併發

redis replication 的核心機制

  • redis 採用異步方式複製數據到 slave 節點,不過 redis2.8 開始,slave node 會週期性地確認自己每次複製的數據量;
  • 一個 master node 是可以配置多個 slave node 的;
  • slave node 也可以連接其他的 slave node;
  • slave node 做複製的時候,不會 block master node 的正常工作;
  • slave node 在做複製的時候,也不會 block 對自己的查詢操作,它會用舊的數據集來提供服務;但是複製完成的時候,需要刪除舊數據集,加載新數據集,這個時候就會暫停對外服務了;
  • slave node 主要用來進行橫向擴容,做讀寫分離,擴容的 slave node 可以提高讀的吞吐量。

注意,如果採用了主從架構,那麼建議必須開啟 master node 的持久化,不建議用 slave node 作為 master node 的數據熱備,因為那樣的話,如果你關掉 master 的持久化,可能在 master 宕機重啟的時候數據是空的,然後可能一經過複製, slave node 的數據也丟了。

另外,master 的各種備份方案,也需要做。萬一本地的所有文件丟失了,從備份中挑選一份 rdb 去恢復 master,這樣才能確保啟動的時候,是有數據的,即使採用了後續講解的高可用機制,slave node 可以自動接管 master node,但也可能 sentinel 還沒檢測到 master failure,master node 就自動重啟了,還是可能導致上面所有的 slave node 數據被清空。

redis 主從複製的核心原理

當啟動一個 slave node 的時候,它會發送一個 PSYNC 命令給 master node。

如果這是 slave node 初次連接到 master node,那麼會觸發一次 full resynchronization 全量複製。此時 master 會啟動一個後臺線程,開始生成一份 RDB 快照文件,同時還會將從客戶端 client 新收到的所有寫命令緩存在內存中。RDB 文件生成完畢後, master 會將這個 RDB 發送給 slave,slave 會先寫入本地磁盤,然後再從本地磁盤加載到內存中,接著 master 會將內存中緩存的寫命令發送到 slave,slave 也會同步這些數據。slave node 如果跟 master node 有網絡故障,斷開了連接,會自動重連,連接之後 master node 僅會複製給 slave 部分缺少的數據。


分佈式系統之Redis主從架構


主從複製的斷點續傳

從 redis2.8 開始,就支持主從複製的斷點續傳,如果主從複製過程中,網絡連接斷掉了,那麼可以接著上次複製的地方,繼續複製下去,而不是從頭開始複製一份。

master node 會在內存中維護一個 backlog,master 和 slave 都會保存一個 replica offset 還有一個 master run id,offset 就是保存在 backlog 中的。如果 master 和 slave 網絡連接斷掉了,slave 會讓 master 從上次 replica offset 開始繼續複製,如果沒有找到對應的 offset,那麼就會執行一次 resynchronization。

如果根據 host+ip 定位 master node,是不靠譜的,如果 master node 重啟或者數據出現了變化,那麼 slave node 應該根據不同的 run id 區分。

無磁盤化複製

master 在內存中直接創建 RDB,然後發送給 slave,不會在自己本地落地磁盤了。只需要在配置文件中開啟 repl-diskless-sync yes 即可。

<code>repl-diskless-sync yes

# 等待 5s 後再開始複製,因為要等更多 slave 重新連接過來
repl-diskless-sync-delay 5/<code>

過期 key 處理

slave 不會過期 key,只會等待 master 過期 key。如果 master 過期了一個 key,或者通過 LRU 淘汰了一個 key,那麼會模擬一條 del 命令發送給 slave。

複製的完整流程

slave node 啟動時,會在自己本地保存 master node 的信息,包括 master node 的host和ip,但是複製流程沒開始。

slave node 內部有個定時任務,每秒檢查是否有新的 master node 要連接和複製,如果發現,就跟 master node 建立 socket 網絡連接。然後 slave node 發送 ping 命令給 master node。如果 master 設置了 requirepass,那麼 slave node 必須發送 masterauth 的口令過去進行認證。master node 第一次執行全量複製,將所有數據發給 slave node。而在後續,master node 持續將寫命令,異步複製給 slave node。


分佈式系統之Redis主從架構


全量複製

  • master 執行 bgsave ,在本地生成一份 rdb 快照文件。
  • master node 將 rdb 快照文件發送給 slave node,如果 rdb 複製時間超過 60秒(repl-timeout),那麼 slave node 就會認為複製失敗,可以適當調大這個參數(對於千兆網卡的機器,一般每秒傳輸 100MB,6G 文件,很可能超過 60s)
  • master node 在生成 rdb 時,會將所有新的寫命令緩存在內存中,在 slave node 保存了 rdb 之後,再將新的寫命令複製給 slave node。
  • 如果在複製期間,內存緩衝區持續消耗超過 64MB,或者一次性超過 256MB,那麼停止複製,複製失敗。
<code>client-output-buffer-limit slave 256MB 64MB 60/<code>
  • slave node 接收到 rdb 之後,清空自己的舊數據,然後重新加載 rdb 到自己的內存中,同時基於舊的數據版本對外提供服務。
  • 如果 slave node 開啟了 AOF,那麼會立即執行 BGREWRITEAOF,重寫 AOF。

增量複製

  • 如果全量複製過程中,master-slave 網絡連接斷掉,那麼 slave 重新連接 master 時,會觸發增量複製。
  • master 直接從自己的 backlog 中獲取部分丟失的數據,發送給 slave node,默認 backlog 就是 1MB。
  • master 就是根據 slave 發送的 psync 中的 offset 來從 backlog 中獲取數據的。

heartbeat

主從節點互相都會發送 heartbeat 信息。

master 默認每隔 10秒 發送一次 heartbeat,slave node 每隔 1秒 發送一個 heartbeat。

異步複製

master 每次接收到寫命令之後,先在內部寫入數據,然後異步發送給 slave node。

redis 如何才能做到高可用

如果系統在 365 天內,有 99.99% 的時間,都是可以嘩嘩對外提供服務的,那麼就說系統是高可用的。

一個 slave 掛掉了,是不會影響可用性的,還有其它的 slave 在提供相同數據下的相同的對外的查詢服務。

但是,如果 master node 死掉了,會怎麼樣?沒法寫數據了,寫緩存的時候,全部失效了。slave node 還有什麼用呢,沒有 master 給它們複製數據了,系統相當於不可用了。

redis 的高可用架構,叫做 failover 故障轉移,也可以叫做主備切換。

master node 在故障時,自動檢測,並且將某個 slave node 自動切換為 master node 的過程,叫做主備切換。這個過程,實現了 redis 的主從架構下的高可用。


分享到:


相關文章: