什么是Sentinel?
定義
Sentinel(哨兵)是Redis的高可用性(hign availability)解決方案:又一個(gè)或多個(gè)Sentinel實(shí)例(instance)組成的Sentinel系統(tǒng)(System)可以監(jiān)視任意多個(gè)主從服務(wù)器,以及這些主從服務(wù)器屬下的所有從服務(wù)器,并在被監(jiān)視的主服務(wù)器進(jìn)入下線狀態(tài)時(shí),自動(dòng)將下線服務(wù)器屬下的某個(gè)從服務(wù)器升級(jí)為新的主服務(wù)器,然后由新的主服務(wù)器代替已下線的主服務(wù)器繼續(xù)處理命令請求。
簡單描述
Sentinel可以實(shí)現(xiàn)高可用,例如,主服務(wù)宕機(jī),可以讓其他服務(wù)頂上,不至于業(yè)務(wù)崩潰。

server1已下線

升級(jí)server2為主服務(wù)器

server1 重連后會(huì)轉(zhuǎn)為從服務(wù)器

Sentinel能解決什么問題?
- 解決單節(jié)點(diǎn)風(fēng)險(xiǎn)問題
- 當(dāng)主服務(wù)器宕機(jī)時(shí),自動(dòng)選取從服務(wù)器作為主服務(wù)器
Sentinel如何實(shí)踐?
修改sentinel.conf 監(jiān)控master服務(wù)
監(jiān)控主機(jī)服務(wù)器
sentinel monitor mymaster 127.0.0.1 6379 1增加主機(jī)服務(wù)器密碼配置(當(dāng)主機(jī)服務(wù)設(shè)置了密碼),此設(shè)置需放置在上一個(gè)設(shè)置之后,否則會(huì)提示
No such master with specified name.
sentinel auth-pass mymaster 123456
驗(yàn)證Sentinel
啟動(dòng)sentinel
有兩種方式啟動(dòng)Sentinel,兩種方式效果完全相同
redis-sentinel sentinel.conf
redis-server sentinel.conf --sentinel啟動(dòng)master
redis-server ../redis.conf &啟動(dòng)slave
redis-server ../redis6378.conf &sentinel 配置信息
port 26379
protected-mode no
dir "/tmp"
sentinel myid 9b14990799b61a813022e2a52cd72665848f7d1f
sentinel monitor mymaster xxx.xxx.xxx.xxx 6379 1
sentinel auth-pass mymaster dev34516
sentinel config-epoch mymaster 20
sentinel leader-epoch mymaster 20

- 查看sentinel信息
info sentinel

可以看到 監(jiān)控到master服務(wù)狀態(tài)正常,并且有一個(gè)slave服務(wù)。
kill掉master服務(wù)

可以發(fā)現(xiàn)mymaster的狀態(tài)已經(jīng)更新為odown狀態(tài)

檢查客戶端連接

過一段時(shí)間后,發(fā)現(xiàn)sentinel已經(jīng)將6378設(shè)置成為了master,并且查看6378的角色已經(jīng)裝為master
使用RedisTemplate測試Redis sentinel
配置信息
redis:
password: xxxx
sentinel:
master: mymaster
nodes: xxx.xxx.xxx.xxx:26379
單元測試
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringSessionTestApplicationTests {
@Autowired
UserService userService ;
@Autowired
StringRedisTemplate stringRedisTemplate;
@Test
public void contextLoads() {
}
@Test
public void testRedisSentinel2(){
String key = "testSentine2" ;
String value = "this is a value2" ;
userService.setString(key,value);
stringRedisTemplate.opsForValue().set(key,value);
assert value.equals(userService.getString(key));
}
}
Sentinel原理
Sentinel初始化
使用Sentinel專用代碼
Sentinel模式下,Redis不能執(zhí)行諸如SET、DBSIZE、EVAL等命令,因?yàn)榉?wù)器根本沒有在命令列表中載入這些命令。-
初始化Sentinel狀態(tài)
Sentinel模式下,服務(wù)器會(huì)初始化一個(gè)sentinel.c/sentinelState結(jié)構(gòu),這個(gè)結(jié)構(gòu)保存了服務(wù)器中所有和Sentinel功能有關(guān)的狀態(tài)
image.png
-
Sentinel創(chuàng)建主服務(wù)器實(shí)例
image.png Sentinel 監(jiān)聽
對于每個(gè)被Sentinel監(jiān)聽的主服務(wù)器來說,Sentinel會(huì)創(chuàng)建兩個(gè)連向主服務(wù)器的異步網(wǎng)絡(luò)連接
1、一個(gè)是命令連接,這個(gè)連接專門用于向主服務(wù)器發(fā)送命令,并接受命令回復(fù)。
2、另一個(gè)是訂閱命令,這個(gè)鏈接專門用于訂閱主服務(wù)器的sentinel:hello頻道。

-
Sentinel 發(fā)現(xiàn)slave服務(wù)器
Sentinel默認(rèn)會(huì)以每10秒一次的頻率,通過命令連接向被監(jiān)視的主服務(wù)器發(fā)送INFO命令,并通過分析INFO命令的回復(fù)來獲取主服務(wù)器的當(dāng)前信息。
image.png
通過分析INFO中的信息,Sentinel會(huì)分別為三分從服務(wù)器創(chuàng)建各自的實(shí)例結(jié)構(gòu),并將這些結(jié)構(gòu)保存到主服務(wù)器實(shí)例結(jié)構(gòu)的slaves字典里面。

Sentinel發(fā)現(xiàn)主服務(wù)器有新的從服務(wù)器出現(xiàn)時(shí),Sentinel除了會(huì)為這個(gè)新的服務(wù)器創(chuàng)建相應(yīng)的實(shí)例結(jié)構(gòu)之外,Sentinel還會(huì)創(chuàng)建連接到從服務(wù)器的命令連接和訂閱連接。

Sentinel檢測下線
主觀下線
默認(rèn)情況下,Sentinel會(huì)以每秒一次向所有與它創(chuàng)建了命令連接的實(shí)例(包括主服務(wù)器、從服務(wù)器、其他Sentinel在內(nèi))發(fā)送PING命令,并通過實(shí)例返回的PING命令回復(fù)來判斷實(shí)例是否在線。
Sentinel配置文件中down-after-milliseconds選項(xiàng)指定了Sentinel判斷實(shí)例進(jìn)入主觀下限所需的時(shí)間長度。如果一個(gè)實(shí)例在down-after-milliseconds毫秒內(nèi),連續(xù)向Sentinel返回?zé)o效回復(fù),那么此Sentinel認(rèn)為該實(shí)例已下線。
客觀下線
當(dāng)Sentinel將一個(gè)主服務(wù)器判斷為主觀下線后,為了確認(rèn)這個(gè)服務(wù)器是否真的下線了,它會(huì)向同樣監(jiān)視這一主服務(wù)器的其他Sentinel詢問,看它們是否也認(rèn)為主服務(wù)器已經(jīng)進(jìn)入下線狀態(tài)。當(dāng)Sentinel從其他Sentinel那里接收到足夠數(shù)量的已下線判斷之后,Sentinel就會(huì)將從服務(wù)器判斷為客觀下線,并對主服務(wù)器執(zhí)行故障轉(zhuǎn)移。
選舉領(lǐng)頭Sentinel
當(dāng)一個(gè)主服務(wù)器被判斷為客觀下線后,只能有一個(gè)Sentinel對該服務(wù)器進(jìn)行故障轉(zhuǎn)移。所以,所有監(jiān)聽此服務(wù)器的Sentinel需要選出一個(gè)帶頭大哥來做這件事情。
選舉有以下規(guī)則與方法
1、所有在線的Sentinel都有被選為領(lǐng)頭Sentinel的資格
2、每次選舉后,不論是否陳宮,所有Sentinel的配置紀(jì)元(configuration epoch)加一。該配置只是一個(gè)計(jì)數(shù)器功能
3、在一個(gè)配置紀(jì)元中,每個(gè)Sentinel都有一次將某個(gè)Sentinel設(shè)置為局部領(lǐng)頭Sentinel的機(jī)會(huì)。
4、Sentinel設(shè)置規(guī)則是先到先得,最先向目標(biāo)Sentinel發(fā)送設(shè)置的將成為Sentinel的局部領(lǐng)頭Sentinel
5、如果某個(gè)Sentinel被半數(shù)以上的Sentinel設(shè)置成為了局部領(lǐng)頭Sentinel,那么這個(gè)Sentinel成為領(lǐng)頭Sentinel。
6、每一個(gè)配置紀(jì)元里面,只能出現(xiàn)一個(gè)領(lǐng)頭Sentinel。
7、如果給定時(shí)間內(nèi),沒有選出來領(lǐng)頭Sentinel,過一段時(shí)間,將再次選舉,直到選出領(lǐng)頭Sentinel。

故障轉(zhuǎn)移
領(lǐng)頭Sentinel會(huì)對已下線的主服務(wù)器進(jìn)行故障轉(zhuǎn)移,分為三個(gè)步驟
1、在已下線主服務(wù)器屬下的所有從服務(wù)器里面,挑選一個(gè)從服務(wù)器,將其轉(zhuǎn)換為主服務(wù)器
2、讓已下線主服務(wù)器屬下的所有從服務(wù)器改為復(fù)制新的主服務(wù)器
3、將已下線主服務(wù)器設(shè)置為新的主服務(wù)器的從服務(wù)器,當(dāng)舊的主服務(wù)器重新上線時(shí),它就會(huì)成為新的主服務(wù)器的從服務(wù)器。






