1. 程式人生 > >Redis詳解(九)------ 哨兵(Sentinel)模式詳解

Redis詳解(九)------ 哨兵(Sentinel)模式詳解

  在上一篇部落格----Redis詳解(八)------ 主從複製,我們簡單介紹了Redis的主從架構,但是這種主從架構存在一個問題,當主伺服器宕機,從伺服器不能夠自動切換成主伺服器,為了解決這個問題,我們又介紹了哨兵模式,本篇部落格我們繼續深入的介紹一下這種模式.

1、架構圖

  

 

 

2、伺服器列表

  

3、搭建主從模式

  ①、主要配置項

  主伺服器(上圖的Node1)配置檔案 redis.config 主要配置項:

#配置埠
port 6379
#以守護程序模式啟動
daemonize yes
#pid的存放檔案
pidfile /var/run/redis_6379.pid
#日誌檔名
logfile "redis_6379.log"
#存放備份檔案以及日誌等檔案的目錄
dir "/opt/redis/data"

  從伺服器配置檔案主要配置項基本和主伺服器保持一致,需要修改埠 port ;另外存放位置和日誌檔名也可以根據需要修改.

  為了表示主從關係,還需要在從伺服器配置檔案中新增一行重要配置:

#配置主伺服器IP,埠
slaveof 192.168.14.101 6379

  ②、驗證主從關係

  配置完成後,我們通過 redis-server redis.conf 命令啟動Redis.然後通過 redis-cli -p 埠 分別進入到各臺伺服器的控制行頁面:

  輸入如下命令:

info replication

  三臺伺服器列印結果如下:

  由上圖可以看到,Node1 伺服器作為主伺服器,節點角色是 master,另外的兩臺從伺服器,節點角色都是 slave.

  另外還可以進行如下測試:可以在主伺服器上新增一條資料,然後看看從伺服器上是否能夠查到該資料.

  ③、問題

  如果對於上面的測試,主伺服器上新增的資料,從伺服器上無法查詢到,可以檢視前面配置的目錄/opt/redis/data 日誌檔案,有一種錯誤如下:

  

  這是由於主伺服器設定了登入密碼,從伺服器在向主伺服器進行資料同步複製時,由於不知道主伺服器密碼,導致連線不上,從而無法進行同步.

  解決這個問題,需要明確兩個配置:

  一.requreipass

  設定redis的登入密碼.

  二.masterauth

  針對master對應的slave節點設定的,在slave節點資料同步的時候用到。

  建議,如果啟用Redis密碼校驗,最好將各個節點的masterauth和requirepass設定為相同的密碼;如果不設定為相同的,要注意slave節點masterauth和master節點requirepass的對應關係.

4、搭建哨兵模式

  ①、主要配置項  

  配置檔名稱為:sentinel.conf

#配置埠
port 26379
#以守護程序模式啟動
daemonize yes
#日誌檔名
logfile "sentinel_26379.log"
#存放備份檔案以及日誌等檔案的目錄
dir "/opt/redis/data" 
#監控的IP 埠號 名稱 sentinel通過投票後認為mater宕機的數量,此處為至少2個
sentinel monitor mymaster 192.168.14.101 6379 2
#30秒ping不通主節點的資訊,主觀認為master宕機
sentinel down-after-milliseconds mymaster 30000
#故障轉移後重新主從複製,1表示序列,>1並行
sentinel parallel-syncs mymaster 1
#故障轉移開始,三分鐘內沒有完成,則認為轉移失敗
sentinel failover-timeout mymaster 180000

  注意三臺伺服器的埠配置.如果redis伺服器配置了密碼連線,則要增加如下配置:

sentinel auth-pass mymaster 123

  後面的123表示密碼.注意這行配置要配置到 sentinel monitor mymaster ip port 後面,因為名稱 mymaster要先定義.

  ②、啟動哨兵

redis-sentinel sentinel.conf

  ③、驗證主從自動切換

  首先kill掉Redis 主節點.然後檢視sentinel 日誌:

  

 

  上面截圖紅框框住的幾個重要資訊,這裡先介紹最後一行,switch-master mymaster 192.168.14.101 6379 192.168.14.103 6381 表示master伺服器將由6379的redis服務切換為6381埠的redis伺服器.

  PS:+switch-master 表示切換主節點.

  然後我們通過 info replication 命令檢視 6381的redis伺服器:

  

  我們發現,6381的Redis服務已經切換成master節點了. 

  另外,也可以檢視sentinel.conf 配置檔案,裡面的 sentinel monitor mymaster 192.168.14.101 6379 2 也自動更改為 sentinel monitor mymaster 192.168.14.103 6381 2 配置了.

5、Java客戶端連線哨兵叢集

  這裡通過springboot專案來連線,程式碼地址如下:

https://github.com/YSOcean/redis-sentinel.git

  這裡貼一下主要測試程式碼:

  PS:實際上springboot已經為我們注入了RedisTemplate,我們在實際專案中不用寫的像下面程式碼這麼麻煩,這樣寫是為了詳細的表明連線步驟.

//1.設定sentinel 各個節點集合
Set<String> sentinelSet = new HashSet<>();
sentinelSet.add("192.168.14.101:26379");
sentinelSet.add("192.168.14.102:26380");
sentinelSet.add("192.168.14.103:26381");

//2.設定jedispool 連線池配置檔案
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(10);
config.setMaxWaitMillis(1000);

//3.設定mastername,sentinelNode集合,配置檔案,Redis登入密碼
JedisSentinelPool jedisSentinelPool = new JedisSentinelPool("mymaster",sentinelSet,config,"123");
Jedis jedis = null;
try {
    jedis = jedisSentinelPool.getResource();
    //獲取Redis中key=hello的值
    String value = jedis.get("hello");
    System.out.println(value);
} catch (Exception e) {
    e.printStackTrace();
} finally {
    if(jedis != null){
        jedis.close();
    }
}

6、Java客戶端連線原理

  ①、結構圖

  

  ②、連線步驟 

  一.客戶端遍歷所有的 Sentinel 節點集合,獲取一個可用的 Sentinel 節點.

  二.客戶端向可用的 Sentinel 節點發送 get-master-addr-by-name 命令,獲取Redis Master 節點.

  三.客戶端向Redis Master節點發送role或role replication 命令,來確定其是否是Master節點,並且能夠獲取其 slave節點資訊.

  四.客戶端獲取到確定的節點資訊後,便可以向Redis傳送命令來進行後續操作了

  需要注意的是:客戶端是和Sentinel來進行互動的,通過Sentinel來獲取真正的Redis節點資訊,然後來操作.實際工作時,Sentinel 內部維護了一個主題佇列,用來儲存Redis的節點資訊,並實時更新,客戶端訂閱了這個主題,然後實時的去獲取這個佇列的Redis節點資訊.

7、哨兵模式工作原理

  ①、三個定時任務

  一.每10秒每個 sentinel 對master 和 slave 執行info 命令:該命令第一個是用來發現slave節點,第二個是確定主從關係.

  二.每2秒每個 sentinel 通過 master 節點的 channel(名稱為_sentinel_:hello) 交換資訊(pub/sub):用來互動對節點的看法(後面會介紹的節點主觀下線和客觀下線)以及自身資訊.

  三.每1秒每個 sentinel 對其他 sentinel 和 redis 執行 ping 命令,用於心跳檢測,作為節點存活的判斷依據.

  ②、主觀下線和客觀下線

  一.主觀下線

  SDOWN:subjectively down,直接翻譯的為”主觀”失效,即當前sentinel例項認為某個redis服務為”不可用”狀態.

  二.客觀下線

  ODOWN:objectively down,直接翻譯為”客觀”失效,即多個sentinel例項都認為master處於”SDOWN”狀態,那麼此時master將處於ODOWN,ODOWN可以簡單理解為master已經被叢集確定為”不可用”,將會開啟故障轉移機制.

  結合我們第4點搭建主從模式,驗證主從切換時,kill掉Redis主節點,然後檢視 sentinel 日誌,如下:

  

  發現有類似 sdown 和 odown 的日誌.在結合我們配置 sentinel 時的配置檔案來看:

#監控的IP 埠號 名稱 sentinel通過投票後認為mater宕機的數量,此處為至少2個
sentinel monitor mymaster 192.168.14.101 6379 2

  最後的 2 表示投票數,也就是說當一臺 sentinel 發現一個 Redis 服務無法 ping 通時,就標記為 主觀下線 sdown;同時另外的 sentinel 服務也發現該 Redis 服務宕機,也標記為 主觀下線,當多臺 sentinel (大於等於2,上面配置的最後一個)時,都標記該Redis服務宕機,這時候就變為客觀下線了,然後進行故障轉移.

  ③、故障轉移

  故障轉移是由 sentinel 領導者節點來完成的(只需要一個sentinel節點),關於 sentinel 領導者節點的選取也是每個 sentinel 向其他 sentinel 節點發送我要成為領導者的命令,超過半數sentinel 節點同意,並且也大於quorum ,那麼他將成為領導者,如果有多個sentinel都成為了領導者,則會過段時間在進行選舉.

  sentinel 領導者節點選舉出來後,會通過如下幾步進行故障轉移:

  一.從 slave 節點中選出一個合適的 節點作為新的master節點.這裡的合適包括如下幾點:

    1.選擇 slave-priority(slave節點優先順序)最高的slave節點,如果存在則返回,不存在則繼續下一步判斷.

    2.選擇複製偏移量最大的 slave 節點(複製的最完整),如果存在則返回,不存在則繼續.

    3.選擇runId最小的slave節點(啟動最早的節點)

  二.對上面選出來的 slave 節點執行 slaveof no one 命令讓其成為新的 master 節點.

  三.向剩餘的 slave 節點發送命令,讓他們成為新master 節點的 slave 節點,複製規則和前面設定的 parallel-syncs 引數有關.

  四.更新原來master 節點配置為 slave 節點,並保持對其進行關注,一旦這個節點重新恢復正常後,會命令它去複製新的master節點資訊.(注意:原來的master節點恢復後是作為slave的角色)

  可以從 sentinel 日誌中出現的幾個訊息來進行檢視故障轉移:

  1.+switch-master:表示切換主節點(從節點晉升為主節點)

  2.+sdown:主觀下線

  3.+odown:客觀下線

  4.+convert-to-slave:切換從節點(原主節點降為從節點)