Redis之主從複製(Sentinel)
基於Redis自身的主從複製模式,一旦Master掛掉,那麼需要手動將Slave節點晉升為Master,而且還需要通知應用方更新Master節點地址,所以這種方式肯定不能接受。所以為了解決這個Redis高可用問題,Redis哨兵即Sentinel誕生。
一Sentinel概念
1.1 主從複製
Redis主從複製模式,可以將主節點資料改變同步給從節點,這樣從節點就起到了2個作用:備份和擴充套件主節點讀的能力。
問題:
# 主節點出現問題,需要手動切換從節點為主節點,你並且通知客戶端主節點變化
# 主節點寫的能力受單機限制
# 主節點儲存能力受單機限制
1.2Sentinel的高可用性
當主節點出現故障的時候,Redis Sentinel能夠自動完成故障發現和故障轉移。並通知應用方從而實現真正的高可用。
Redis Sentinel 是一個分散式架構,其中包含 若干個Sentinel節點和Redis資料節點,每一個Sentinel會對資料節點和其他Sentinel節點進行監控,當他發現節點不可達時,會對節點做下線標識。如果被標識的是主節點,他還會和其他節點Sentinel節點協商,當大多數Sentinel節點都認為主節點不可達的時候,會選舉一個Sentinel節點來完成自動故障轉移的工作,並且會將這個變化實時通知給Redis應用方。整個過程是自動的,完全不需要人工來干預。
注意: Sentinel也是Redis節點,只不過他不是用於儲存資料。
1.3Sentinel的功能
# 監控: Sentinel節點會定期檢測其他Sentinel節點和Redis資料節點
# 通知: Sentinel會將故障轉移的結果通知給應用方
# 主節點故障轉移: 選出新主節點,然後維護後續正確的主從關係
二Sentinel 安裝部署
2.1 部署拓撲圖
2.2 部署Redis資料節點
2.2.1 配置主節點
port 6379
bind 192.168.1.201
daemonize yes
pidfile /opt/app/sentinel/master/redis.pid
logfile /opt/app/sentinel/master/logs/redis.log
appendonly yes
dir /opt/app/sentinel/master/data
啟動主節點:bin/redis-servercon/redis.conf
2.2.2 配置從節點
Slave-01配置:
port 6379
bind 192.168.1.202
daemonize yes
pidfile /opt/app/sentinel/slave1/redis.pid
logfile /opt/app/sentinel/slave1/logs/redis.log
appendonly yes
dir /opt/app/sentinel/slave1/data
slaveof 192.168.1.201 6379
Slave-02配置:
port 6379
bind 192.168.1.203
daemonize yes
pidfile /opt/app/sentinel/slave2/redis.pid
logfile /opt/app/sentinel/slave2/logs/redis.log
appendonly yes
dir /opt/app/sentinel/slave2/data
slaveof 192.168.1.201 6379
啟動從節點
bin/redis-server conf/redis.conf
2.2.3 確認主從關係
bin/redis-cli -h 192.168.1.201 -p 6379 inforeplication
檢查主從關係是否確立
2.3 部署Sentinel節點
# monitor 指定需要監控主節點
sentinel monitor <master-name> <ip><redis-port> <quorum>
master-name:指定的master名字
ip: 要監聽的資料主節點節點IP地址
redis-port:要監聽的資料主節點埠
quorum:為確認這個主伺服器已下線所需要的最少Sentinel數量
# down-after-milliseconds 指定了 Sentinel 認為伺服器已經斷線所需的毫秒數
sentinel down-after-milliseconds<master-name> <milliseconds>
# failover-timeout 指定了故障轉移的超時時間,
sentinel failover-timeout <master-name><milliseconds>
# parallel-syncs 指定了在執行故障轉移時, 最多可以有多少個從伺服器同時對新的主伺服器進行同步
sentinel parallel-syncs mymaster 1
2.3.1 配置和啟動三個Sentinel節點
Sentinel1節點:
port 26379
bind 0.0.0.0
dir "/opt/app/sentinel/sentinel1/data"
daemonize yes
pidfile /opt/app/sentinel/sentinel1/sentinel.pid
logfile"/opt/app/sentinel/sentinel1/logs/sentinel.log"
sentinel monitor mymaster 192.168.1.201 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1
Sentinel2節點:
port 26379
bind 0.0.0.0
dir "/opt/app/sentinel/sentinel2/data"
daemonize yes
pidfile /opt/app/sentinel/sentinel2/sentinel.pid
logfile "/opt/app/sentinel/sentinel2/logs/sentinel.log"
sentinel monitor mymaster 192.168.1.201 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1
Sentinel3節點:
port 26379
bind 0.0.0.0
dir "/opt/app/sentinel/sentinel3/data"
daemonize yes
pidfile /opt/app/sentinel/sentinel3/sentinel.pid
logfile "/opt/app/sentinel/sentinel3/logs/sentinel.log"
sentinel monitor mymaster 192.168.1.201 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1
檢視sentinel資訊
bin/redis-cli -h 192.168.1.201 -p 6379 infosentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=192.168.1.201:6379,slaves=2,sentinels=3
2.3.2 配置優化
# sentinel master
需要監視的主節點IP和埠以及quorum,quorum這個表示多少個sentinel節點認為主節點已經掛掉了,才視為主節點下線,即客觀下線; 同時quorum還跟sentinel節點的leader選舉有關係,至少要max(quorum,sentinel節點數/2 + 1)個sentinel節點參加選舉,才能選舉出leader,從而進行故障轉移。
# sentinel down-after-milliseconds
每一個sentinel節點都會向主節點,從節點和其他sentinel節點1秒鐘ping一次。在down-after-milliseconds毫秒內沒有進行回覆,sentinel節點就會判定該節點失敗,這個行為叫做主觀下線。
# sentinel parallel-syncs
當sentinel領導者開始進行故障轉移的時候,選出新的主節點,原來的從節點會向新的主節點發起復制操作,parallel-syncs就是用來限制在一次故障轉移之後,每次向新的主節點同時發起複製操作節點個數。如果這個值較大, 雖然一般不會阻塞主節點,但是會給網路和磁碟IO帶來開銷。
# sentinel failover-timeout
故障轉移超時時間
# sentinel auth-pass
如果sentinel監控的主節點設定了密碼,sentinel auth-pass配置通過新增主節點的密碼,防止sentinel節點對主節點無法監控。
# sentinel notification-script
在故障轉移期間,當一些警告級別的sentinel事件發生時,會觸發對應的指令碼,並向指令碼傳送相對應的事件引數。
2.4 如何監控多個主節點
sentinel monitor master1 192.168.1.201 6379 2
sentinel down-after-milliseconds master1 30000
sentinel failover-timeout master1 180000
sentinel parallel-syncs master1 1
sentinel monitor master2 192.168.1.202 6379 2
sentinel down-after-milliseconds master2 30000
sentinel failover-timeout master2 180000
sentinel parallel-syncs master2 1
2.5 部署技巧
2.4.1sentinel節點儘量不要部署在一臺物理機上
2.4.2sentinel節點至少三個而且是奇數
2.4.3 如果是同一個業務的多個主節點,可以使用一套sentinel,否則就使用多套sentinel
三Sentinel 客戶端
無論哪一種程式語言的客戶端,如果需要正確的連線Redis Sentinel,必須有Sentinel節點集合和主節點引數。
3.1Redis Sentinel 客戶端基本實現原理
實現一個Redis Sentinel客戶端的基本步驟如下:
# 遍歷sentinel節點集合獲取一個可用的sentinel節點,從任意一個sentinel節點獲取主節點資訊都是可以的
# 通過sentinel get-master-addr-by-name master-name獲取主節點資訊
# 驗證當前獲取的主節點是真正的主節點,防止故障轉移期間的主節點變化
# 保持和sentinel節點的聯絡,時刻獲取關於主節點相關的資訊
3.2Java操作Redis Sentinel
private static JedisSentinelPoolgetSentinelPool(String
masterName,Set<String>
sentinels) {
if (StringUtils.isBlank(masterName) ||
CollectionUtils.isEmpty(sentinels)) {
return null;
}
JedisPoolConfig config
= new JedisPoolConfig();
config.setMaxTotal(1024);
config.setMaxIdle(200);
config.setMaxWaitMillis(1000);
return new JedisSentinelPool(masterName,sentinels,config);
}
四 Sentinel實現原理
4.1 三個定時監控任務
Redis通過三個定時任務完成對各個節點的監控:
4.1.1每隔10秒,每個Sentinel節點會向Master節點和Slave節點發送方info命令獲取最新的拓撲結構,比如:
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.1.202,port=6379,state=online,offset=67874,lag=1
slave1:ip=192.168.1.203,port=6379,state=online,offset=68015,lag=0
對上述結果解析就可以找到相應的從節點。
該定時任務的作用:
# 向主節點發送info命令獲取從節點資訊,所以sentinel不需要顯示配置監控從節點
# 當有新的從節點加入,可以立刻感知出來
# 節點不可達,或者故障轉移後,可通過info命令實時更新拓撲資訊
4.1.2 每隔2秒,每一個sentinel 節點會向Redis資料節點的__sentinel__:hello 頻道上傳送該sentinel節點對於主節點的判斷以及當前sentinel節點的資訊,同時每一個sentinel節點也會訂閱該頻道
4.1.3 每隔1秒,每一個sentinel節點會向主節點,從節點,其餘sentinel節點發送一條ping命令,做一次心跳檢測,來確認這些節點當前是否可達
4.2 主觀下線和客觀下線
4.2.1主觀下線
當sentinel對主節點,從節點和其他sentinel節點發送ping命令進行心跳檢測,如果超過down-after-milliseconds沒有進行回覆,Sentinel節點就會判定該節點失敗,這個行為叫做主觀下線
4.2.2 客觀下線
當sentinel主觀下線是主節點的時候,該sentinel會通過sentinel is-master-down-by-addr,命令向其他sentinel節點詢問對主節點的判斷,當超過quorum個數的sentinel節點認為主節點確實存在問題,這時候sentinel節點會做出客觀下線的決定
4.3 領導者Sentinel節點的選舉
當sentinel節點對於主節點已經做了客觀下線,也不是立刻就進行故障轉移,在轉移還需要選舉一個leader專門用來處理故障轉移。Redis使用Raft演算法實現領導者選舉。
大致過程如下:
# 每一個線上的sentinel節點都有資格成為領導者,當它確認主節點主觀下線的時候,會向其他節點發送sentinel is-master-down-by-addr命令,要求將自己設定為leader
# 收到命令的sentinel節點,如果沒有同意過其他其他sentinel的節點is-master-down-by-addr命令,將同一該請求,否則拒絕
# 如果該sentinel發現自己的票數已經大於等於max(quorum,sentinel節點數/2+1),那麼它將成為領導者
# 如果此過程沒有選舉出leader,將進入下一次選舉
所以我們也可以這樣理解,誰最先確認主節點客觀下線,誰最有可能成為Leader.
4.4 故障轉移
4.4.1 從從節點列表選擇一個節點作為新的主節點,選擇方法如下:
# 過濾不健康的從節點
# 選擇slave-priority最高的,如果存在即返回,不存在就繼續
# 選擇複製偏移量最大的從節點,如果存在即返回,不存在就繼續
# 選擇runid最小的從節點
4.4.2 sentinelleader會對前一步選擇的從節點執行slaveof no one命令,讓其成為主節點
4.4.3sentinel leader向剩餘的從節點發送命令,讓他們成為新的主節點的從節點,複製規則和parallel-sync引數有關係
4.4.4sentinel節點集合會將原來的主節點更新為從節點,並保持對其關注,當起恢復後命令其去複製新的主節點
五Sentinel開發與運維
5.1 節點下線
臨時下線:暫時關掉節點,之後會重新啟動
永久下線:關閉之後永遠不會再使用,有時候還需要做一些清理工作,比如等
5.1.1 主節點下線
sentinel failover <master name>
5.1.2 從節點和sentinel節點
如果使用了讀寫分離,下線從節點需要保證應用方可以感知從節點的下線變化,並把讀請求路由到其他節點。
5.2 節點上線
5.2.1 新增從節點
有時候比如只有一臺節點的情況下,想使用主從,支撐故障轉移;或者使用的讀寫分離,不能支撐應用方的流量
slaveof <masterip> <masterport> 的配置,使用redis-server啟動即可,他將被 sentinel節點自動發現。
5.2.2 新增sentinel節點
當前sentinel節點數量不夠,無法達到健壯性的要求或者無法達到票數;或者之前的sentinel節點需要下線
新增配置然後正常啟動sentinel即可,被其餘的sentinel節點自動發現