1. 程式人生 > >redis高可用sentinel叢集搭建

redis高可用sentinel叢集搭建

哨兵機制,它基於 Redis 主從複製,主要作用便是解決主節點故障恢復的自動化問題,進一步提高系統的高可用性。

哨兵的架構

在這裡插入圖片描述

它由兩部分組成,哨兵節點和資料節點:
哨兵節點:哨兵系統由一個或多個哨兵節點組成,哨兵節點是特殊的 Redis 節點,不儲存資料。
資料節點:主節點和從節點都是資料節點。

獲取redis
wget http://download.redis.io/releases/redis-3.2.12.tar.gz
解壓 、編譯

配置一個簡單的redis sentinel 叢集,一個主節點 兩個從節點,和3個哨兵節點。

主從複製配置
#主redis-6380.conf
在這裡插入圖片描述

port 6380
#開啟守護執行緒 後臺執行
daemonize yes
logfile “6380.log”
dbfilename “dump-6380.rdb”
#注意 bind要開啟 可以指定ip 也可以設定0.0.0.0

#從節點 redis-6381.conf
在這裡插入圖片描述

port 6381
#開啟守護執行緒 後臺執行
daemonize yes
logfile “6381.log”
dbfilename “dump-6381.rdb”
#設定主節點的ip和埠
slaveof 127.0.0.1 6380
#注意 bind要開啟 可以指定ip 也可以設定0.0.0.0

#從節點 redis-6382.conf
在這裡插入圖片描述

port 6382
#開啟守護執行緒 後臺執行
daemonize yes
logfile “6382.log”
dbfilename “dump-6382.rdb”
#設定主節點的ip和埠
slaveof 127.0.0.1 6380
#注意 bind要開啟 可以指定ip 也可以設定0.0.0.0

配置完成後再依次啟動redis服務
在這裡插入圖片描述
./redis-3.2.12/src/redis-server redis-6380.conf
./redis-3.2.12/src/redis-server redis-6381.conf
./redis-3.2.12/src/redis-server redis-6382.conf

啟動完成之後 我們可以通過客戶端的工具檢視一下配置主從節點的資訊
./redis-3.2.12/src/redis-cli -p 6380
#檢視主從複製資訊
info Replication
在這裡插入圖片描述
上圖顯示 連線的slave 節點有兩個,並可以清楚的檢視slave資訊。

哨兵節點的配置

哨兵節點本質是特殊的節點,不儲存任何資料,只是負責監控資料節點。而哨兵節點的配置也是很簡單的,區別在於埠修改。
配置哨兵
#sentinel-26380.conf
在這裡插入圖片描述
#sentinel-26381.conf
在這裡插入圖片描述
#sentinel-26382.conf
在這裡插入圖片描述
配置完成後,啟動哨兵節點。

./redis-3.2.12/src/redis-sentinel sentinel-26380.conf
./redis-3.2.12/src/redis-sentinel sentinel-26381.conf
./redis-3.2.12/src/redis-sentinel sentinel-26382.conf
也可以通過redis-server啟動 加上 --sentinel引數
./redis-3.2.12/src/redis-server sentinel-26382.conf --sentinel
啟動完成之後,我們可以通過redis的客戶端工具連線檢視一下。
#使用 info Sentinel 命令檢視
在這裡插入圖片描述
slaves 表示有兩個從節點,sentinel 表示有3個哨兵正在執行的狀態。

啟動完成之後 我們可以通過命令檢視sentinel的配置檔案
#cat sentinel-26380.conf
在這裡插入圖片描述

測試故障轉移
在這裡插入圖片描述
我們看到現在的主節點是6381 ,直接結束6381埠的程序 kill -9 1502
在這裡插入圖片描述
在檢視主節點的資訊
在這裡插入圖片描述
發現主節點的資訊已經切換到了6382上,在故障轉移切換的時候,會自動的修改配置檔案

在這裡插入圖片描述
優先將第一位的推選為主節點。
哨兵會登陸到6382的服務中,並修改 為主節點 ,命令為 slaveof no one,再登陸到其他服務中修改為從節點,執行的命令為 slaveof 127.0.0.1 6382

在這裡插入圖片描述

哨兵配置

sentinel monitor {masterName} {masterIp} {masterPort}{quorum}
sentinel monitor 是哨兵最核心的配置,在前文講述部署哨兵節點時已說明,其中:masterName 指定了主節點名稱,masterIp 和 masterPort 指定了主節點地址,quorum 是判斷主節點客觀下線的哨兵數量閾值。
當判定主節點下線的哨兵數量達到 quorum 時,對主節點進行客觀下線。建議取值為哨兵數量的一半加 1。

sentinel down-after-milliseconds {masterName} {time}
sentinel down-after-milliseconds 與主觀下線的判斷有關:哨兵使用 ping 命令對其他節點進行心跳檢測。如果其他節點超過 down-after-milliseconds 配置的時間沒有回覆,哨兵就會將其進行主觀下線,該配置對主節點、從節點和哨兵節點的主觀下線判定都有效。
down-after-milliseconds 的預設值是 30000,即 30s;可以根據不同的網路環境和應用要求來調整。
值越大,對主觀下線的判定會越寬鬆,好處是誤判的可能性小,壞處是故障發現和故障轉移的時間變長,客戶端等待的時間也會變長。
例如,如果應用對可用性要求較高,則可以將值適當調小,當故障發生時儘快完成轉移;如果網路環境相對較差,可以適當提高該閾值,避免頻繁誤判。

sentinel parallel-syncs {masterName} {number}
sentinel parallel-syncs 與故障轉移之後從節點的複製有關:它規定了每次向新的主節點發起復制操作的從節點個數。
例如,假設主節點切換完成之後,有 3 個從節點要向新的主節點發起復制;如果 parallel-syncs=1,則從節點會一個一個開始複製;如果 parallel-syncs=3,則 3 個從節點會一起開始複製。

parallel-syncs 取值越大,從節點完成複製的時間越快,但是對主節點的網路負載、硬碟負載造成的壓力也越大;應根據實際情況設定。
例如,如果主節點的負載較低,而從節點對服務可用的要求較高,可以適量增加 parallel-syncs 取值。parallel-syncs 的預設值是 1。

sentinel failover-timeout {masterName} {time}
sentinel failover-timeout 與故障轉移超時的判斷有關,但是該引數不是用來判斷整個故障轉移階段的超時,而是其幾個子階段的超時。
例如如果主節點晉升從節點時間超過 timeout,或從節點向新的主節點發起復制操作的時間(不包括複製資料的時間)超過 timeout,都會導致故障轉移超時失敗。

failover-timeout 的預設值是 180000,即 180s;如果超時,則下一次該值會變為原來的 2 倍。

通過這些命令,可以查詢哨兵系統的拓撲結構、節點資訊、配置資訊等:
info sentinel:獲取監控的所有主節點的基本資訊。
sentinel masters:獲取監控的所有主節點的詳細資訊。
sentinel master mymaster:獲取監控的主節點 mymaster 的詳細資訊。
sentinel slaves mymaster:獲取監控的主節點 mymaster 的從節點的詳細資訊。
sentinel sentinels mymaster:獲取監控的主節點 mymaster 的哨兵節點的詳細資訊。
sentinel get-master-addr-by-name mymaster:獲取監控的主節點 mymaster 的地址資訊,前文已有介紹。
sentinel is-master-down-by-addr:哨兵節點之間可以通過該命令詢問主節點是否下線,從而對是否客觀下線做出判斷。

小結
哨兵系統的搭建過程,有幾點需要注意:
哨兵系統中的主從節點,與普通的主從節點並沒有什麼區別,故障發現和轉移是由哨兵來控制和完成的。
哨兵節點本質上是 Redis 節點。
每個哨兵節點,只需要配置監控主節點,便可以自動發現其他的哨兵節點和從節點。
在哨兵節點啟動和故障轉移階段,各個節點的配置檔案會被重寫(config rewrite)。
本文的例子中,一個哨兵只監控了一個主節點;實際上,一個哨兵可以監控多個主節點,通過配置多條 sentinel monitor 即可實現

客戶端訪問哨兵系統

     public static void sentinel() throws Exception {
         String masterName = "mymaster";
         Set<String> sentinels = new HashSet<>();
         sentinels.add("192.168.1.128:26379");
         sentinels.add("192.168.1.128:26380");
         sentinels.add("192.168.1.128:26381");
         
         qweqweJedisSentinelPool pool = new JedisSentinelPool(masterName, sentinels); //初始化過程做了很多工作
         Jedis jedis = pool.getResource();
         jedis.set("key1", "value1");
         pool.close();
  	}