一、主從複製存在的問題
一旦主節點出現故障, 需要手動將一個從節點晉升爲主節點, 同時需要修改應用方的主節點地址, 還需要命令其他從節點去複製新的主節點, 整個過程都需要人工干預。
二、高可用 redis sentinel
1、概述:
Redis Sentinel是一個分佈式架構, 其中包含若干個Sentinel節點和Redis數據節點, 每個Sentinel節點會對數據節點和其餘Sentinel節點進行監控, 當它發現節點不可達時, 會對節點做下線標識。 如果被標識的是主節點, 它還會和其他Sentinel節點進行“協商”, 當大多數Sentinel節點都認爲主節點不可達時, 它們會選舉出一個Sentinel節點來完成自動故障轉移的工作, 同時會將這個變化實時通知給Redis應用方。 整個過程完全是自動的, 不需要人工來介入。
它的主要功能有以下幾點
- 多個sentinel發現並確認master有問題
- 選舉出一個sentinel作爲領導
- 選出一個slave作爲master
- 通知其餘slave成爲新的master的slave
- 通知客戶端主從變化
- 等待老的master復活成爲新的master的slave
2、安裝與配置
①配置開啓主從節點
7001端口配置,7002類似。
有兩個從節點
②配置開啓sentinel監控主節點(sentinel是特殊的redis)
配置:
- Sentinel節點的默認端口是26379。
- sentinel monitor mymaster 127.0.0.1 7000 2配置代表sentinel-1節點需要監控127.0.0.1: 7000這個主節點, 2代表判斷主節點失敗至少需要2個Sentinel節點同意, mymaster是主節點的別名
啓動sentinel
redis-sentinel redis-sentinel-26381.conf
當三個Sentinel節點都啓動後,拓撲結構圖如下:
注意:
- 生產環境中建議Redis Sentinel的所有節點應該分佈在不同的物理機上。
- Redis Sentinel中的數據節點和普通的Redis數據節點在配置上沒有任何區別, 只不過是添加了一些Sentinel節點對它們進行監控。
三、redis-sentinel實現原理
1、sentinel 集羣通過三個定時監控任務完成對各個節點發現和監控。
1、每10秒每個sentinel對master和slave執行info
- 發現slave節點
- 確認主從關係
作用:
sentinel 集羣可以得知 master 和 slave 的基本信息,①通過向主節點執行 info 命令,獲取從節點的信息,所以 sentinel 節點不需要顯式配置監控從節點,②當有新的從節點加入時都可以立刻感知出來,③當 master 節點故障或者故障轉移後,可以通過 info 命令實時更新 redis 主從信息。
2、 每隔2秒,每個 sentinel 節點會向 redis 數據節點的
__sentinel__:hello
這個channel(頻道)發送一條消息。每個sentinel都會訂閱該頻道。信息交互平臺:信息交換、領導者選舉該定時任務的作用:
- 發現新的 sentinel節點:通過訂閱主節點的
__sentinel__:hello
瞭解其他的 sentinel 節點信息,如果是新加入的 sentinel 節點,將該 sentinel 節點信息保存起來,並與該 sentinel 節點創建連接。- sentinel 節點之間交換主節點的狀態,用做 master 下線和故障處理的 leader 選舉的依據。
3、每隔1秒, 每個Sentinel節點會向主節點、 從節點、 其餘Sentinel節點發送一條ping命令做一次心跳檢測, 來確認這些節點當前是否可達。
通過定時發送ping命令,sentinel 節點對主節點、從節點、其餘 sentinel 節點都建立起連接,實現了對每個節點的監控,這個定時任務是節點下線判定的重要依據。
2、主觀下線和客觀下線
sentinel monitor mymaster 127.0.0.1 6379 2
master名 法定人數<quorum> 建議節點數/2+1,超過50%。讓我想起了區塊鏈
sentinel down-after-milliseconds mymaster 30000 #超時下線
master名 30s
sentinel is-master-down-by-addr <ip> <port> <current_epoch> <runid> #問一下別的sentinel是否master該下線了
1、主觀下線
每個 sentinel 節點每隔1秒對主節點、從節點、其他 sentinel 節點發送 ping 命令做心跳檢測,當這些節點超過
down-after-milliseconds
沒有進行有效回覆,sentinel節點就會認爲該節點下線,這個行爲叫做主觀下線。主觀下線是某個 sentinel 節點的判斷,並不是 sentinel 集羣的判斷,所以存在誤判的可能。
2、客觀下線
當 sentinel 主觀下線的節點是主節點時,該 sentinel 節點會通過
sentinel ismaster-down-by-addr
命令向其他 sentinel 節點詢問對主節點的判斷,當超過<quorum>個(quorum可配置)sentinel 節點認爲主節點有問題,這時該 sentinel 節點會做出客觀下線的決定,也就是大部分(超過50%)是 sentinel 節點都對主節點的下線做了同意的判定,那麼這個判定就是客觀的。sentinel is-master-down-by-addr <ip> <port> <current_epoch> <runid> ·ip: 主節點IP。 ·port: 主節點端口。 ·current_epoch: 當前配置紀元。 ·runid: 此參數有兩種類型, 不同類型決定了此API作用的不同。 當runid等於“*”時, 作用是Sentinel節點直接交換對主節點下線的判定。 當runid等於當前Sentinel節點的runid時, 作用是當前Sentinel節點希望目標Sentinel節點同意自己成爲領 導者的請求, 有關Sentinel領導者選舉, 後面會進行介紹。
如果發送:sentinel is-master-down-by-addr 127.0.0.1 6379 0 *
返回三個參數:
- down_state: 目標Sentinel節點對於主節點的下線判斷, 1是下線, 0是在線。
- leader_runid: 當leader_runid等於“*”時, 代表返回結果是用來做主節點是否不可達, 當leader_runid等於具體的runid, 代表目標節點同意runid成爲領導者。
- leader_epoch: 領導者紀元。
3、故障轉移前的領導者節點選舉
當 sentinel 集羣確認 master 下線,需要選舉出一個 leader 節點來進行故障轉移
選舉:通過sentinel is-master-down-by-addr命令都希望成爲領導者
- 每個做主觀下線的Sentinel節點向其他Sentinel節點發送命令,要求將它設置爲領導者。
- 收到命令的Sentinel節點如果沒有同意通過其他Sentinel節點發送的命令,那麼將同意該請求,否則拒絕。
- 如果該Sentinel節點發現自己的票數已經超過Sentinel集合半數且超過quorum ,那麼它將成爲領導者。
- 如果此過程有多個Sentinel節點成爲了領導者,那麼將等待一段時間重新進行選舉。
4、故障轉移(sentinel領導者節點做)
1、從slave節點中選取一個“合適的”節點作爲新的master節點。
- 選擇slave-priority(優先級)最高的slave節點,如果存在則返回,不存在則繼續。
- 選擇複製偏移量最大的slave節點,如果存在則返回,不存在則繼續。
- 選擇runid最小的slave節點。
2、對上面的slave執行slave no one命令讓它成爲master節點。
3、向剩餘的slave節點發送命令,讓它們成爲新的master的slave節點。複製master節點。
4、更新原來的master爲slave,並一直“關注”,當它恢復後,命令它去複製新的master節點。
四、讀寫分離
從節點也可以用來擴展主節點的讀能力,尤其是在讀多寫少的場景下。
但是存在一個問題:從節點不是高可用的,如果從節點出現故障,與其相連的客戶端獲取不到服務。其次,主節點沒有客觀下線,客觀下線只針對主節點。
方法:
在設計Redis Sentinel的從節點高可用時, 只要能夠實時掌握所有從節點的狀態(可以依賴Sentinel節點的消息通
知, 獲取Redis數據節點的狀態變化), 把所有從節點看做一個資源池 , 無論是上線還是下線從節點, 客戶端都能及時感知到(將其從資源池中添加或者刪除) , 這樣從節點的高可用目標就達到了。