做者 | codedump codedump.info 博主,多年從事互聯網服務器後臺開發工做。可訪問做者博客閱讀 codedump 更多文章。redis
導讀:Redis是被普遍使用的基礎軟件之一。對於工程師和架構師、運維人員來講,瞭解Redis的高可用方案和背後的原理,是必備的基礎知識。本文做者深刻分析了Redis高可用的方方面面,而且作了有效總結,相信對廣大讀者能夠起到很好的領路做用。數據庫
Redis中爲了實現高可用(High Availability,簡稱HA),採用了以下兩個方式:服務器
主從複製數據。網絡
採用哨兵監控數據節點的運行狀況,一旦主節點出現問題由從節點頂上繼續進行服務。架構
主從複製運維
Redis中主從節點複製數據有全量複製和部分複製之分。分佈式
舊版本全量複製功能的實現性能
全量複製使用snyc命令來實現,其流程是:阿里雲
從服務器向主服務器發送sync命令。3d
主服務器在收到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> <offset>命令,其中runid是上一次主服務器的運行id,offset是當前從服務器的複製偏移量。
前面兩種狀況主服務器收到psync命令以後,會出現如下三種可能:
主服務器返回+fullresync <runid> <offset>回覆,表示主服務器要求與從服務器進行完整的數據全量同步操做。其中,runid是當前主服務器運行id,而offset是當前主服務器的複製偏移量。
若是主服務器應答+continue,那麼表示主服務器與從服務器進行部分數據同步操做,將從服務器缺失的數據同步過來便可。
若是主服務器應答-err,那麼表示主服務器版本低於2.8,識別不了psync命令,此時從服務器將向主服務器發送sync命令,執行完整的全量數據同步。
哨兵機制概述
Redis使用哨兵機制來實現高可用(HA),其大概工做原理是:
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」命令,讓該節點成爲主節點。
哨兵領導者向剩餘的從節點發送命令,讓它們成爲新主節點的從節點。
哨兵節點集合會將原來的主節點更新爲從節點,當其恢復以後命令它去複製新的主節點的數據。
若是過程當中哨兵領導者失效怎麼辦?不妨來6月21-23日即將於深圳舉辦的GIAC全球互聯網架構大會聽聽掌閱資深架構師,暢銷圖書《Redis 深度歷險:核心原理與應用實踐》做者錢文品怎麼說,他將做爲數據庫專場的講師出席2019年GIAC深圳站,並作關於Redis高性能,高可用方面的的演講。此外,阿里雲前數據庫總負責人餘峯將做爲本專場的出品人,具體議題以下: