Redis高可用原理,這下能看懂了吧

Redis 是被廣泛使用的基礎軟件之一,對於架構師和運維人員來說,瞭解 Redis 的高可用方案和背後的原理,是必備的基礎知識。

在這裏插入圖片描述

本文作者深入分析了 Redis 高可用的方方面面,並且做了有效總結,相信對廣大讀者可以起到很好的領路作用。

Redis 中爲了實現高可用採用瞭如下兩個方式:

主從複製數據。
採用哨兵監控數據節點的運行情況,一旦主節點出現問題由從節點頂上繼續進行服務。

主從複製

Redis 中主從節點複製數據有全量複製和部分複製之分。

舊版本全量複製功能的實現

在這裏插入圖片描述

全量複製使用 Snyc 命令來實現,其流程是:

從服務器向主服務器發送 Sync 命令。
主服務器在收到 Sync 命令之後,調用 Bgsave 命令生成最新的 RDB 文件,將這個文件同步給從服務器,這樣從服務器載入這個 RDB 文件之後,狀態就會和主服務器執行 Bgsave 命令時候的一致。
主服務器將保存在命令緩衝區中的寫命令同步給從服務器,從服務器執行這些命令,這樣從服務器的狀態就跟主服務器當前狀態一致了。

舊版本全量複製功能,其最大的問題是從服務器斷線重連時,即便在從服務器上已經有一部分數據了,也需要進行全量複製,這樣做的效率很低,於是新版本的 Redis 在這部分做了改進。

新版本全量複製功能的實現

新版本 Redis 使用 Psync 命令來代替 Sync 命令,該命令既可以實現完整全同步也可以實現部分同步。

複製偏移量

執行復制的雙方,主從服務器,分別會維護一個複製偏移量:

主服務器每次向從服務器同步了 N 字節數據之後,將修改自己的複製偏移量 +N。
從服務器每次從主服務器同步了 N 字節數據之後,將修改自己的複製偏移量 +N。

複製積壓緩衝區

在這裏插入圖片描述

主服務器內部維護了一個固定長度的先進先出隊列做爲複製積壓緩衝區,其默認大小爲 1MB。

在主服務器進行命令傳播時,不僅會將寫命令同步到從服務器,還會將寫命令寫入複製積壓緩衝區。

服務器運行 ID

每個 Redis 服務器,都有其運行 ID,運行 ID 由服務器在啓動時自動生成,主服務器會將自己的運行 ID 發送給從服務器,而從服務器會將主服務器的運行 ID 保存起來。

從服務器 Redis 斷線重連之後進行同步時,就是根據運行 ID 來判斷同步的進度:

如果從服務器上面保存的主服務器運行 ID 與當前主服務器運行 ID 一致,則認爲這一次斷線重連連接的是之前複製的主服務器,主服務器可以繼續嘗試部分同步操作。
否則,如果前後兩次主服務器運行 ID 不相同,則認爲是完成全同步流程。

Psync 命令流程

有了前面的準備,下面開始分析 Psync 命令的流程:

如果從服務器之前沒有複製過任何主服務器,或者之前執行過 slaveof no one 命令,那麼從服務器就會向主服務器發送 psync ? -1 命令,請求主服務器進行數據的全量同步。
否則,如果前面從服務器已經同步過部分數據,那麼從服務器向主服務器發送 psync 命令,其中 runid 是上一次主服務器的運行 id,offset 是當前從服務器的複製偏移量。
在這裏插入圖片描述
前面兩種情況主服務器收到 Psync 命令之後,會出現以下三種可能:

主服務器返回 +fullresync 回覆,表示主服務器要求與從服務器進行完整的數據全量同步操作。其中,runid 是當前主服務器運行 id,而 offset 是當前主服務器的複製偏移量。
如果主服務器應答 +continue,那麼表示主服務器與從服務器進行部分數據同步操作,將從服務器缺失的數據同步過來即可。
如果主服務器應答 -err,那麼表示主服務器版本低於 2.8,識別不了 Psync 命令,此時從服務器將向主服務器發送 Sync 命令,執行完整的全量數據同步。

哨兵機制概述

Redis 使用哨兵機制來實現高可用的大概工作原理是:

Redis 使用一組哨兵(Sentinel)節點來監控主從 Redis 服務的可用性。
一旦發現 Redis 主節點失效,將選舉出一個哨兵節點作爲領導者(Leader)。
哨兵領導者再從剩餘的從 Redis 節點中選出一個 Redis 節點作爲新的主 Redis 節點對外服務。

以上將 Redis 節點分爲兩類:

哨兵節點(Sentinel):負責監控節點的運行情況。
數據節點:即正常服務客戶端請求的 Redis 節點,有主從之分。

以上是大體的流程,這個流程需要解決以下幾個問題:

如何對 Redis 數據節點進行監控?
如何確定一個 Redis 數據節點失效?
如何選擇出一個哨兵領導者節點?
哨兵節點選擇新的主 Redis 節點的依據是什麼?

以下來逐個回答這些問題。

三個監控任務

哨兵節點通過三個定時監控任務監控 Redis 數據節點的服務可用性。

①info 命令
在這裏插入圖片描述

每隔 10 秒,每個哨兵節點都會向主、從 Redis 數據節點發送 info 命令,獲取新的拓撲結構信息。

Redis 拓撲結構信息包括了:

本節點角色:主或從。
主從節點的地址、端口信息。

這樣,哨兵節點就能從 info 命令中自動獲取到從節點信息,因此那些後續才加入的從節點信息不需要顯式配置就能自動感知。

②向 sentinel:hello 頻道同步信息

每隔 2 秒,每個哨兵節點將會向 Redis 數據節點的 sentinel:hello 頻道同步自身得到的主節點信息以及當前哨兵節點的信息。
在這裏插入圖片描述

由於其他哨兵節點也訂閱了這個頻道,因此實際上這個操作可以交換哨兵節點之間關於主節點以及哨兵節點的信息。

這一操作實際上完成了兩件事情:

發現新的哨兵節點:如果有新的哨兵節點加入,此時保存下來這個新哨兵節點的信息,後續與該哨兵節點建立連接。
交換主節點的狀態信息,作爲後續客觀判斷主節點下線的依據。

③向數據節點做心跳探測

在這裏插入圖片描述

每隔 1 秒,每個哨兵節點向主、從數據節點以及其他 Sentinel 節點發送 Ping 命令做心跳探測,這個心跳探測是後續主觀判斷數據節點下線的依據。

主觀下線和客觀下線

①主觀下線

在這裏插入圖片描述
上面三個監控任務中的第三個探測心跳任務,如果在配置的 down-after-milliseconds 之後沒有收到有效回覆,那麼就認爲該數據節點“主觀下線(sdown)”。

爲什麼稱爲“主觀下線”?因爲在一個分佈式系統中,有多個機器在一起聯動工作,網絡可能出現各種狀況,僅憑一個節點的判斷還不足以認爲一個數據節點下線了,這就需要後面的“客觀下線”。

②客觀下線
在這裏插入圖片描述

當一個哨兵節點認爲主節點主觀下線時,該哨兵節點需要通過”sentinel is-master-down-by addr”命令向其他哨兵節點諮詢該主節點是否下線了,如果有超過半數的哨兵節點都回答了下線,此時認爲主節點“客觀下線”。

選舉哨兵領導者

當主節點客觀下線時,需要選舉出一個哨兵節點做爲哨兵領導者,以完成後續選出新的主節點的工作。
在這裏插入圖片描述

這個選舉的大體思路是:

每個哨兵節點通過向其他哨兵節點發送”sentinel is-master-down-by addr”命令來申請成爲哨兵領導者。
而每個哨兵節點在收到一個”sentinel is-master-down-by addr”命令時,只允許給第一個節點投票,其他節點的該命令都會被拒絕。
如果一個哨兵節點收到了半數以上的同意票,則成爲哨兵領導者。
如果前面三步在一定時間內都沒有選出一個哨兵領導者,將重新開始下一次選舉。

可以看到,這個選舉領導者的流程很像 Raft 中選舉 Leader 的流程。

選出新的主節點
在這裏插入圖片描述

在剩下的 Redis 從節點中,按照以下順序來選擇新的主節點:

過濾掉“不健康”的數據節點:比如主觀下線、斷線的從節點、五秒內沒有回覆過哨兵節點 Ping 命令的節點、與主節點失聯的從節點。
選擇 Slave-Priority(從節點優先級)最高的從節點,如果存在則返回,不存在則繼續後面的流程。
選擇複製偏移量最大的從節點,這意味着這個從節點上面的數據最完整,如果存在則返回,不存在則繼續後面的流程。
到了這裏,所有剩餘從節點的狀態都是一樣的,選擇 runid 最小的從節點。

提升新的主節點

在這裏插入圖片描述

選擇了新的主節點之後,還需要最後的流程讓該節點成爲新的主節點:

哨兵領導者向上一步選出的從節點發出“slaveof no one”命令,讓該節點成爲主節點。
哨兵領導者向剩餘的從節點發送命令,讓它們成爲新主節點的從節點。
哨兵節點集合會將原來的主節點更新爲從節點,當其恢復之後命令它去複製新的主節點的數據。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章