915
技術社區[雲棲]
Redis開發運維實踐高可用和集群架構與實踐(一)
11.1 主從複製-sentinel架構
11.1.1 高可用原理
11.1.1.1 發現原理
Sentinel發現分為發現從服務器和發現其他sentinel服務兩類:
- Sentinel實例可以通過詢問主實例來獲得所有從實例的信息
- Sentinel進程可以通過發布與訂閱來自動發現正在監視相同主實例的其他Sentinel,每個 Sentinel 都訂閱了被它監視的所有主服務器和從服務器的 __sentinel__:hello 頻道, 查找之前未出現過的 sentinel進程。 當一個 Sentinel 發現一個新的 Sentinel 時,它會將新的 Sentinel 添加到一個列表中,這個列表保存了 Sentinel 已知的,監視同一個主服務器的所有其他Sentinel。
注:文中的橫杠要替換為下滑線,markdown不太能顯示出來...
11.1.1.2 基本切換原理
在切換中,配置文件是會被動態修改的,例如當發生主備切換時候,配置文件中的master會被修改為另外一個slave。這樣,之後sentinel如果重啟時,就可以根據這個配置來恢複其之前所監控的redis集群的狀態。 在sentinel切換過程中有三大步驟:
- 判斷是否下線(老主是否真的咽氣駕崩) 每個sentinel在監控的時候,每秒對主進行一次ping命令,如果多次ping的響應時間超過了配置文件中的down-after-milliseconds,那麼這個哨兵就會認為被監控的實例是SDown狀態(Subjectively Down,主觀down,SDOWN)。 這個時候此sentinel會判斷此master是否真的掛了——即可以設置成ODOWN(Objectively Down,客觀down,ODOWN)。設置成ODOWN的條件是除了當前sentinel認為此master SDOWN,還必須有其他sentinel認為此master SDOWN,當認為SDOWN的sentinel的個數等於或超過配置文件中monitor master最後的那個參數quorum後,就sentinel就會認為此master是ODOWN。 被標記為ODOWN的另一個效應是:在一般情況下,每個 Sentinel 進程會以每 10 秒一次的頻率向它已知的所有主實例和從實例發送 INFO 命令。 當一個主實例被 Sentinel實例標記為客觀下線時, Sentinel 向ODOWN Master的所有從實例發送 INFO 命令的頻率會從 10 秒一次改為每秒一次。
-
進行投票選舉主持切換的sentinel(選舉一個長老,由它來欽點新帝王) 當master被認為是ODOWN的時候,可能需要進行failover,但是並不是odown了就可以執行failover,因為可能有多個sentinel都認為master是odown了,這時候就需要選舉一個sentiel來執行failover。也就是說切換之前要先選舉一個sentinel來主持切換,條件是必須有>=max(quorum, num(sentinels)/2 +1)的sentinel都同意某一個sentinel主持failover,那麼這個sentinel就可以主持failover,超過半數這個條件就能限製住此時刻隻有一個sentinel來操作。 這個也是通過is-master-down-by-addr消息進行更新每個sentinel的選舉的leader。每個sentinel都有一個epoch,這個東西相當於一個時間戳,是遞增的值,如果集群正常的話,所有的sentinel的這個值都是一樣的。當master出現異常後,每個sentinel後自增這個值,如果一直沒有選舉出來leader的話,這個值會跟隨這time event的輪詢,每次加一,在設定的故障遷移超時時間的兩倍之後, 重新嚐試當選。同時is-master-down-by-addr會把這個值發送到其他的sentinel,其他的sentinel收到這個消息後,會判斷自己的epoch和消息中的epoch,如果自己的epoch小於消息中的epoch,那麼其他的sentinel就會選舉傳遞消息的這個sentinel。最終會大部分sentinel都同意一個較大的epoch的sentinel主持failover。
-
進行切換,並其他實例同步新Master(新帝王登基,其餘藩王宣誓效忠新帝王) 這個主持切換的sentinel選出一個從redis實例,並將它升級為Master。首先是要下麵的條件按照如下條件篩選備選node: 1) slave節點狀態處於S_DOWN,O_DOWN,DISCONNECTED的除外 2) 最近一次ping應答時間不超過5倍ping的間隔(假如ping的間隔為1秒,則最近一次應答延遲不應超過5秒,redis sentinel默認為1秒) 3) info_refresh應答不超過3倍info_refresh的間隔(原理同2,redis sentinel默認為10秒) 4) slave節點與master節點失去聯係的時間不能超過( (now - master->s_down_since_time) + (master->down_after_period * 10))。總體意思是說,slave節點與master同步太不及時的(比如新啟動的節點),不應該參與被選舉。 5) Slave priority不等於0(這個是在配置文件中指定,默認配置為100)。
然後再從備選node中,按照如下順序選擇新的master 1) 較低的slave_priority(這個是在配置文件中指定,默認配置為100) 2) 較大的replication offset(每個slave在與master同步後offset自動增加) 3) 較小的runid(每個redis實例,都會有一個runid,通常是一個40位的隨機字符串,在redis啟動時設置,重複概率非常小) 4) 如果以上條件都不足以區別出唯一的節點,則會看哪個slave節點處理之前master發送的command多,就選誰。 主持切換的sentinel向被選中的從redis實例發送 SLAVEOF NO ONE 命令,讓它轉變為Master。然後通過發布與訂閱功能,將更新後的配置傳播給所有其他 Sentinel,其他 Sentinel 對它們自己的配置進行config-rewrite。隨後sentinel向已下線的Master的從服務器發送SLAVEOF命令,讓它們去複製新Master。
注意:sentinel failover-timeout這個選項有四個含義,有必要在此翻譯一下 1) 對於一個sentinel選出的同一個master進行再次的failover嚐試所需要的時間——這個參數值的兩倍。 2) 當sentinel發現一個slave錯誤的複製了一個錯的主時sentinel會強迫其複製正確的主的時間。 3) 取消一個已經開始但是還沒有引起任何配置改變的failover所需要的時間。 4) 等待所有slave被重新配置為新主的slave而所需要的最大時間。注意即使超過了這個時間sentinel也會最終配置slave去同步最新的master
最後更新:2017-05-08 11:31:08