滿懷憂思,不如先幹再說!
主從複制出現的問題
上篇文章《Redis主從複制》中我們說到可以對Redis單節點資料進行備份實作Redis高可用,但是如果master節點當機并不會自動做故障切換等,導緻項目中更可能需要接入多資料源,編寫代碼實作故障切換非常麻煩,Redis考慮到這個問題提供了哨兵模式,也就是Redis Sentinel!
Redis Sentinel基本架構
看圖我們說一下Redis Sentinel架構,首先我們需要加入Sentinel節點,Sentinel節點去監控Redis中Master和Slave的運作狀态,判斷是否可用,當然Sentinel節點也是有多個的,實作Sentinel節點的高可用和多節點判斷Redis節點是否可用不會出現誤判情況
用戶端不再直接操作Redis的Master或者Slave節點,而是去通路Sentinel節點!是以我們的用戶端會記錄Redis Sentinel的位址!我們的用戶端不關心誰是Master而是Sentinel告訴用戶端誰是Master,背景Master切換了,用戶端也不會受到影響!
當多個sentinel發現并确認master出現問題,會選舉出一個sentinel作為上司,選舉出一個slave為新的master,通知其餘的slave有新的master産生,通知用戶端master發生變化,等待老的master複活成為新的master的slave!
一套sentinel可以同時監控多套master和slave!節省資源!每套master/slave會有一個master-name作為辨別以示差別
安裝和配置
叢集規劃
- 配置開啟主從節點,一個master端口号為7000,兩個slave節點分别問7001和7002;
- 配置開啟sentinel監控主節點。(sentinel是特殊的redis節點,不存儲資料),三個sentinel分别為26379,26380,26381;
配置描述
master
port 7000
daemonize yes
pidfile /var/run/redis/redis-7000.pid
logfile "7000.log"
dir "/usr/local/redis-5.0.5/data/"
slave-7001
指令:sed "s/7000/7001/g" redis-7000.conf > redis-7001.conf
将7000替換為7001
指令:echo "slaveof stt101 7000" >> redis-7001.conf
重定向slaveof stt101 7000到redis-7001.conf檔案末尾
port 7001
daemonize yes
pidfile /var/run/redis/redis-7001.pid
logfile "7001.log"
dir "/usr/local/redis-5.0.5/data/"
slaveof stt101 7000
slave-7002
port 7002
daemonize yes
pidfile /var/run/redis/redis-7002.pid
logfile "7002.log"
dir "/usr/local/redis-5.0.5/data/"
slaveof stt101 7000
配置完之後啟動三個節點檢視主從關系:
redis-cli -p 7000 info replication
sentinel主要配置
#三台sentinel使用端口差別
port ${port}
dir "/usr/local/redis-5.0.5/data/"
logfile "${port}.log"
#監控主節點名字為mymaster,ip,端口,2台sentinel認為master有問題就會故障轉移
sentinel monitor mymaster ip port 2
#30000毫秒ping不通認為出現問題
sentinel down-after-milliseconds mymaster 30000
#選擇了新的master之後老的slave會對新的slave進行複制,1代表每次隻有一個slave進行複制,減輕master壓力
sentinel parallel-syncs mymaster 1
#故障轉移時間
sentinel failover-timeout mymaster 180000
注意:在redis的安裝目錄下有一個sentinel.conf檔案就是sentinel的配置檔案,我們将這個檔案拷貝到conf目錄下,去除注釋等。給出一個26739的配置,其餘的兩台大家隻需修改端口号了pid檔案即可
第一台的配置
port 26379
daemonize yes
pidfile "/var/run/redis/redis-sentinel-26379.pid"
logfile "26379.log"
dir "/usr/local/redis-5.0.5/data"
#stt101為ip映射
sentinel monitor mymaster stt101 7000 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
protected-mode no
#通過該指令将sentinel.conf檔案去掉注釋和換行将内容放到redis-sentinel-26739.conf檔案中
cat sentinel.conf | grep -v "#" | grep -v "^#34; > redis-sentinel-26739.conf
#啟動
redis-sentinel redis-sentinel-26739.conf
#配置其他兩台,三台配置是一樣的,修改端口和日志檔案,pid檔案即可
sed "s/26379/26380/g" redis-sentinel-26379.conf > redis-sentinel-26380.conf
sed "s/26379/26381/g" redis-sentinel-26379.conf > redis-sentinel-26381.conf
啟動
# 使用redis-sentinel指令讀取配置檔案分别啟動三台sentinel節點
# 記得修改檔案名哦
redis-sentinel redis-sentinel-26739.conf
# 分别啟動三台Redis節點
redis-server redis-6379.conf
# 通過用戶端連接配接上sentinel節點
redis-cli -h 192.168.109.101 -p 26379
這裡大家注意一下:有些可能有疑問,上邊端口不是7000嗎下邊咋變成6379了,搞咩啊,之前在寫的時候,這裡有一點小瑕疵,我直接重寫了,端口号上下沒有對應起來,這裡聲明一下,之前的7000,7001,7002分别對應下文的6379,6380,6381,如果沒有發現問題,是不沒認真看啊!
啟動之後檢視狀态
大家看下邊動圖,名字為6379, 6380, 6381的為redis節點,名字為26379的為sentinel節點,示範節點狀态和故障轉移
- 首先在redis sentinel下檢視address是6381,說明其為主節點
- 之後将6381kill掉,等待一段時間,這裡時間大概在30S左右,這段時間我暫停了
- 之後再檢視info資訊,發現address變為6380
SpringBoot內建Redis Sentinel示範
這個思路也很簡單,我們循環添加或者查詢資料,将主節點手動當機,檢視日志列印是否成功切換繼續讀寫資料即可,我們隻需要修改application.yml配置檔案即可
配置檔案
spring:
redis:
#host: 192.168.109.101 #這是之前單機時的ip配置
#port: 6379 # 這個是單機時的端口配置,現在都不用寫了
sentinel:
# 寫sentinel節點的ip:port
nodes: 192.168.109.101:26379,192.168.109.102:26380,192.168.109.103:26381
# 寫sentinel節點的名字,因為sentinel可以有很多組,每一組使用名字區分
master: mymaster
timeout: 2s
#連接配接池最大連接配接數(使用負值表示沒有限制)
max-active: 2000
#連接配接池最大阻塞等待時間(使用負值表示沒有限制)
max-wait: -1ms
#連接配接池中的最大空閑連接配接
max-idle: 1024
#連接配接池中的最小空閑連接配接
min-idle: 100
代碼
/**
添加資料
*/
@Test
public void test7(){
//循環,添加資料
for (int i = 0; i < 200; i++) {
String key = "key-" + i;
String value = "value-" + i;
try {
redisTemplate.opsForValue().set(key,value);
//慢一點
Thread.sleep(500);
System.out.println("目前插入:" + key + "===>" + value);
} catch (InterruptedException e) {
e.printStackTrace();
}catch (Exception e){
e.printStackTrace();
}
}
System.out.println("資料插入完成");
}
/**
查詢資料
*/
@Test
public void test8(){
//編寫循環,添加資料
for (int i = 0; i < 200; i++) {
String key = "key-" + i;
try {
Object o = redisTemplate.opsForValue().get(key);
//慢一點
Thread.sleep(500);
System.out.println("目前擷取:" + o );
} catch (InterruptedException e) {
e.printStackTrace();
}catch (Exception e){
e.printStackTrace();
}
}
}
示範
這裡我又将剛剛關閉的6381節點啟動,三個節點提供服務,進行示範,一樣的動圖送給大家,這裡隻貼出插入資料的動圖了,查詢的類似,大家動手做一做試一下!
基本原理
由三個定時任務實作的切換
每10S一個info
每10秒每個sentinel節點會對master和slave發送一個info指令,一是為了發現slave節點,二是為了确認主從關系
每2秒交換資訊
每2秒每個sentinel通過master節點的channel交換資訊(pub/sub),相當于一個sentinel的互動平台,互動對master/slave狀态的監聽情況和自身的資訊。通過一個名為__sentinel__:hello的頻道互動,每個sentinel節點都會訂閱這個頻道
每秒1ping
每一秒每個sentinel節點對其他sentinel和redis執行一次ping,這一步基于第一步sentinel掌握redis的master和slave節點的狀況,基于第二步sentinel節點知道其他的sentinel節點,對他們進行心跳檢測,判斷是否在正常工作
收藏等于學會!别忘了點贊,關注哦,高頻推出技術文章,有問題記得評論或者私信!