關于Redis高可用方案,看到較多的是keepalived、zookeeper方案,keepalived是主備模式,意味著總有一臺浪費著,zookeeper作業量成本偏高,
本文主要介紹下使用官方sentinel做redis高可用方案的設計,
閱讀目錄:
- Redis Sentinel
- 故障轉移訊息接收的3種方式
- 整體流程圖
- 總結
Redis Sentinel
Sentinel介紹
Sentinel是Redis官方為集群提供的高可用解決方案,在實際專案中可以使用sentinel去做redis自動故障轉移,減少人工介入的作業量,另外sentinel也給客戶端提供了監控訊息的通知,這樣客戶端就可根據訊息型別去判斷服務器的狀態,去做對應的適配操作,
下面是Sentinel主要功能串列:
- Monitoring:Sentinel持續檢查集群中的master、slave狀態,判斷是否存活,
- Notification:在發現某個redis實體死的情況下,Sentinel能通過API通知系統管理員或其他程式腳本,
- Automatic failover:如果一個master掛掉后,sentinel立馬啟動故障轉移,把某個slave提升為master,其他的slave重新配置指向新master,
- Configuration provider:對于客戶端來說sentinel通知是有效可信賴的,客戶端會連接sentinel去請求當前master的地址,一旦發生故障sentinel會提供新地址給客戶端,
Sentinel配置
Sentinel本質上只是一個運行在特殊模式下的redis服務器,通過不同配置來區分提供服務,sentinel.conf配置:
// [監控名稱] [ip] [port] [多少sentinel同意才發生故障轉移]
sentinel monitor mymaster 127.0.0.1 6379 2
// [監控名稱] [Master多少毫秒后不回應ping命令,就認為master是主觀下線狀態]
sentinel down-after-milliseconds mymaster 60000
// [故障轉移超時時間]
sentinel failover-timeout mymaster 180000
//[在執行故障轉移時,最多可以有多少個從服務器同時對新的主服務器進行同步]
sentinel parallel-syncs mymaster 1
sentinel需要使用redis2.8版本以上,啟動如下:
redis-sentinel sentinel.conf
啟動后Sentinel會:
- 以10秒一次的頻率,向被監視的master發送info命令,根據回復獲取master當前資訊,
- 以1秒一次的頻率,向所有redis服務器、包含sentinel在內發送PING命令,通過回復判斷服務器是否在線,
- 以2秒一次的頻率,通過向所有被監視的master,slave服務器發送包含當前sentinel,master資訊的訊息,
另外建議sentinel至少起3個實體以上,并配置2個實體同意即可發生轉移,5個實體,配置3個實體同意以此類推,
故障轉移訊息接收的3種方式
Redis服務器一旦發送故障后,sentinel通過raft演算法投票選舉新master,故障轉移程序可以通過sentinel的API獲取/訂閱接收事件訊息,
搜索Java知音公眾號,回復“后端面試”,送你一份Java面試題寶典.pdf
腳本接收
- 當故障轉移期間,可以指定一個“通知”腳本用來告知系統管理員,當前集群的情況,
- 腳本被允許執行的最大時間為60秒,如果超時,腳本將會被終止(KILL)
sentinel notification-script mymaster /var/redis/notify.sh
- 故障轉移期之后,配置通知客戶端的腳本.
sentinel client-reconfig-script mymaster /var/redis/notifyReconfig.sh
客戶端直接接收
Sentinel的故障轉移訊息通知使用的是redis發布訂閱,就是說在故障轉移期間所有產生的事件資訊,都通過頻道(channel)發布出去,比如我們加臺slave服務器,sentinel監聽到后會發布加slave的訊息到"+slave"頻道上,客戶端只需要訂閱"+slave"頻道即可接收到對應訊息,
其訊息格式如下:
[實體型別] [事件服務器名稱] [服務器ip] [服務器埠] @[master名稱] [ip] [埠]
<instance-type> <name> <ip> <port> @ <master-name> <master-ip> <master-port>
通知訊息格式示例:
* //訂閱型別, *即訂閱所有事件訊息,
-sdown //訊息型別
slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6381
訂閱訊息示例:
using (RedisSentinel rs = new RedisSentinel(CurrentNode.Host, CurrentNode.Port))
{
var redisPubSub = new RedisPubSub(node.Host, node.Port);
redisPubSub.OnMessage += OnMessage;
redisPubSub.OnSuccess += (msg) =>{};
redisPubSub.OnUnSubscribe += (obj) =>{};
redisPubSub.OnError = (exception) =>{ };
redisPubSub.PSubscribe("*");
}
服務間接接收
這種方式在第二種基礎上擴展了一層,即應用端不直接訂閱sentinel,單獨做服務去干這件事情,然后應用端提供API供這個服務回呼通知,這樣做的好處在于:
- 減少應用端監聽失敗出錯的可能性,
- 應用端由主動方變成被動方,降低耦合,
- 性能提高,輪詢變回呼,
- 獨立成服務可擴展性更高,
比如:
1:以后換掉sentinel,我們只需要動服務即可,應用端無需更改,
2:可以在服務內多增加一層守護執行緒去主動拉取redis狀態,這樣可確保即使sentinel不生效,也能及時察覺redis狀態,并通知到應用端,當然這種情況很極端,因為sentinel配的也是多節點,同時掛的幾率非常小,
示例:
應用端提供回呼API,在這個API邏輯下去重繪記憶體中的Redis連接,
http://127.0.0.1/redis/notify.api
獨立服務監控到狀況后,呼叫API通知應用端:
httprequest.post("http://127.0.0/redis/notify.api");
整體設計
推薦使用第三種,其整體流程圖如下:

總結
各種sentinel通知訊息型別見官方檔案,專案中使用的redis客戶端在github上
https://github.com/mushroomsir/HRedis
本文分享了樓主在專案中做Redis高可用的經驗,希望對大家有所幫助,在人力物力滿足的情況下還是推薦使用zookeeper方案的,只有三五桿槍的情況下也就退而求其次,利用最小成本滿足需求并保留可擴展性,
相信沒有最好的架構,只有更合適的架構,
- http://redis.io/topics/sentinel
歡迎關注公眾號 【碼農開花】一起學習成長
我會一直分享Java干貨,也會分享免費的學習資料課程和面試寶典
回復:【計算機】【設計模式】【面試】有驚喜哦
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/230188.html
標籤:其他
