Redis Sentinel-深入淺出原理和實(shí)戰(zhàn)

本篇博客會(huì)簡(jiǎn)單的介紹Redis的Sentinel相關(guān)的原理,同時(shí)也會(huì)在最后的文章給出硬核的實(shí)戰(zhàn)教程,讓你在了解原理之后,能夠?qū)嶋H上手的體驗(yàn)整個(gè)過程。

之前的文章聊到了Redis的主從復(fù)制,聊到了其相關(guān)的原理和缺點(diǎn),具體的建議可以看看我之前寫的文章Redis的主從復(fù)制

總的來說,為了滿足Redis在真正復(fù)雜的生產(chǎn)環(huán)境的高可用,僅僅是用主從復(fù)制是明顯不夠的。例如,當(dāng)master節(jié)點(diǎn)宕機(jī)了之后,進(jìn)行主從切換的時(shí)候,我們需要人工的去做failover。

同時(shí)在流量方面,主從架構(gòu)只能通過增加slave節(jié)點(diǎn)來擴(kuò)展讀請(qǐng)求,寫能力由于受到master單節(jié)點(diǎn)的資源限制是無法進(jìn)行擴(kuò)展的。

這也是為什么我們需要引入Sentinel。

Sentinel

功能概覽

Sentinel其大致的功能如下圖。

Sentinel

Sentinel是Redis高可用的解決方案之一,本身也是分布式的架構(gòu),包含了多個(gè)Sentinel節(jié)點(diǎn)和多個(gè)Redis節(jié)點(diǎn)。而每個(gè)Sentinel節(jié)點(diǎn)會(huì)對(duì)Redis節(jié)點(diǎn)和其余的Sentinel節(jié)點(diǎn)進(jìn)行監(jiān)控。

當(dāng)其發(fā)現(xiàn)某個(gè)節(jié)點(diǎn)不可達(dá)時(shí),如果是master節(jié)點(diǎn)就會(huì)與其余的Sentinel節(jié)點(diǎn)協(xié)商。當(dāng)大多數(shù)的Sentinel節(jié)點(diǎn)都認(rèn)為master不可達(dá)時(shí),就會(huì)選出一個(gè)Sentinel節(jié)點(diǎn)對(duì)master執(zhí)行故障轉(zhuǎn)移,并通知Redis的調(diào)用方相關(guān)的變更。

相對(duì)于主從下的手動(dòng)故障轉(zhuǎn)移,Sentinel的故障轉(zhuǎn)移是全自動(dòng)的,無需人工介入。

Sentinel自身高可用

666,那我怎么知道滿足它自身的高可用需要部署多少個(gè)Sentinel節(jié)點(diǎn)?

因?yàn)镾entinel本身也是分布式的,所以也需要部署多實(shí)例來保證自身集群的高可用,但是這個(gè)數(shù)量是有個(gè)最低的要求,最低需要3個(gè)

我去,你說3個(gè)就3個(gè)?我今天偏偏就只部署2個(gè)

你別杠...等我說了為什么就必須要3個(gè)...

因?yàn)樯诒鴪?zhí)行故障轉(zhuǎn)移需要大部分的哨兵都同意才行,如果只有兩個(gè)哨兵實(shí)例,正常運(yùn)作還好,就像這樣。

<img src="https://tva1.sinaimg.cn/large/0081Kckwgy1glf2ztrzuxj30uc0e0tad.jpg" alt="redis-sentinel" style="zoom: 67%;" />

如果哨兵所在的那臺(tái)機(jī)器由于機(jī)房斷電啊,光纖被挖啊等極端情況整個(gè)掛掉了,那么另一臺(tái)哨兵即使發(fā)現(xiàn)了master故障之后想要執(zhí)行故障轉(zhuǎn)移,但是它無法得到任何其余哨兵節(jié)點(diǎn)的同意,此時(shí)也永遠(yuǎn)無法執(zhí)行故障轉(zhuǎn)移,那Sentinel豈不是成了一個(gè)擺設(shè)?

所以我們需要至少3個(gè)節(jié)點(diǎn),來保證Sentinel集群自身的高可用。當(dāng)然,這三個(gè)Sentinel節(jié)點(diǎn)肯定都推薦部署到不同的機(jī)器上,如果所有的Sentinel節(jié)點(diǎn)都部署到了同一臺(tái)機(jī)器上,那當(dāng)這臺(tái)機(jī)器掛了,整個(gè)Sentinel也就不復(fù)存在了。

<img src="https://tva1.sinaimg.cn/large/0081Kckwgy1glf3ho05rwj31a20pkgp4.jpg" alt="redis-sentinel-success" style="zoom:67%;" />

quorum&majority

大部分?大哥這可是要上生產(chǎn)環(huán)境,大部分這個(gè)數(shù)量未免也太敷衍了,咱就不能專業(yè)一點(diǎn)?

前面提到的大部分哨兵同意涉及到兩個(gè)參數(shù),一個(gè)叫quorum,如果Sentinel集群有quorum個(gè)哨兵認(rèn)為master宕機(jī)了,就客觀的認(rèn)為master宕機(jī)了。另一個(gè)叫majority...

等等等等,不是已經(jīng)有了一個(gè)叫什么quorum的嗎?為什么還需要這個(gè)majority?

你能不能等我把話說完...

quorum剛剛講過了,其作用是判斷master是否處于宕機(jī)的狀態(tài),僅僅是一個(gè)判斷作用。而我們?cè)趯?shí)際的生產(chǎn)中,不是說只判斷master宕機(jī)就完了, 我們不還得執(zhí)行故障轉(zhuǎn)移,讓集群正常工作嗎?

同理,當(dāng)哨兵集群開始進(jìn)行故障轉(zhuǎn)移時(shí),如果有majority個(gè)哨兵同意進(jìn)行故障轉(zhuǎn)移,才能夠最終選出一個(gè)哨兵節(jié)點(diǎn),執(zhí)行故障轉(zhuǎn)移操作。

主觀宕機(jī)&客觀宕機(jī)

你剛剛是不是提到了客觀宕機(jī)?笑死,難不成還有主觀宕機(jī)這一說?

1607390948-22870

Sentinel中認(rèn)為一個(gè)節(jié)點(diǎn)掛了有兩種類型:

  • Subjective Down,簡(jiǎn)稱sdown,主觀的認(rèn)為master宕機(jī)
  • Objective Down,簡(jiǎn)稱odown,客觀的認(rèn)為master宕機(jī)

當(dāng)一個(gè)Sentinel節(jié)點(diǎn)與其監(jiān)控的Redis節(jié)點(diǎn)A進(jìn)行通信時(shí),發(fā)現(xiàn)連接不上,此時(shí)這個(gè)哨兵節(jié)點(diǎn)就會(huì)主觀的認(rèn)為這個(gè)Redis數(shù)據(jù)A節(jié)點(diǎn)sdown了。為什么是主觀?我們得先知道什么叫主觀

未經(jīng)分析推算,下結(jié)論、決策和行為反應(yīng),暫時(shí)不能與其他不同看法的對(duì)象仔細(xì)商討,稱為主觀

簡(jiǎn)單來說,因?yàn)橛锌赡?strong>只是當(dāng)前的Sentinel節(jié)點(diǎn)和這個(gè)A節(jié)點(diǎn)的網(wǎng)絡(luò)通信有問題,其余的Sentinel節(jié)點(diǎn)仍然可以和A正常的通信。

<img src="https://tva1.sinaimg.cn/large/0081Kckwgy1glhcj19q37j318o0lmgnb.jpg" alt="sentinel-sdown" style="zoom:50%;" />

這也是為什么我們需要引入odown,當(dāng)大于等于了quorum個(gè)Sentinel節(jié)點(diǎn)認(rèn)為某個(gè)節(jié)點(diǎn)宕機(jī)了,我們就客觀的認(rèn)為這個(gè)節(jié)點(diǎn)宕機(jī)了。

當(dāng)Sentinel集群客觀的認(rèn)為master宕機(jī),就會(huì)從所有的Sentinel節(jié)點(diǎn)中,選出一個(gè)Sentinel節(jié)點(diǎn),來最終執(zhí)行master的故障轉(zhuǎn)移。

那這個(gè)故障轉(zhuǎn)移具體要執(zhí)行些什么操作呢?我們通過一個(gè)圖來看一下。

<img src="https://tva1.sinaimg.cn/large/0081Kckwgy1glg76hj320j31cm0l240z.jpg" alt="sentinel-ops" style="zoom:67%;" />

通知調(diào)用的客戶端master發(fā)生了變化

通知其余的原slave節(jié)點(diǎn),去復(fù)制Sentinel選舉出來的新的master節(jié)點(diǎn)

如果此時(shí)原來的master又重新恢復(fù)了,Sentinel也會(huì)讓其去復(fù)制新的master節(jié)點(diǎn)。成為一個(gè)新的slave節(jié)點(diǎn)。

硬核教程

硬核教程旨在用最快速的方法,讓你在本地體驗(yàn)Redis主從架構(gòu)和Sentinel集群的搭建,并體驗(yàn)整個(gè)故障轉(zhuǎn)移的過程。

前置要求

  1. 安裝了docker
  2. 安裝了docker-compose

準(zhǔn)備compose文件

首先需要準(zhǔn)備一個(gè)目錄,然后分別建立兩個(gè)子目錄。如下。

$ tree .
.
├── redis
│   └── docker-compose.yml
└── sentinel
    ├── docker-compose.yml
    ├── sentinel1.conf
    ├── sentinel2.conf
    └── sentinel3.conf

2 directories, 5 files

搭建Redis主從服務(wù)器

redis目錄下的docker-compose.yml內(nèi)容如下。

version: '3'
services:
  master:
    image: redis
    container_name: redis-master
    ports:
      - 6380:6379
  slave1:
    image: redis
    container_name: redis-slave-1
    ports:
      - 6381:6379
    command:  redis-server --slaveof redis-master 6379
  slave2:
    image: redis
    container_name: redis-slave-2
    ports:
      - 6382:6379
    command: redis-server --slaveof redis-master 6379

以上的命令,簡(jiǎn)單解釋一下slaveof

就是讓兩個(gè)slave節(jié)點(diǎn)去復(fù)制container_name為redis-master的節(jié)點(diǎn),這樣就組成了一個(gè)簡(jiǎn)單的3個(gè)節(jié)點(diǎn)的主從架構(gòu)

然后用命令行進(jìn)入當(dāng)前目錄,直接敲命令docker-compose up即可,剩下的事情交給docker-compose去做就好,它會(huì)把我們所需要的節(jié)點(diǎn)全部啟動(dòng)起來。

此時(shí)我們還需要拿到剛剛我們啟動(dòng)的master節(jié)點(diǎn)的IP,簡(jiǎn)要步驟如下:

  1. 通過docker ps找到對(duì)應(yīng)的master節(jié)點(diǎn)的containerID

    $ docker ps
    CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
    9f682c199e9b        redis               "docker-entrypoint.s…"   3 seconds ago       Up 2 seconds        0.0.0.0:6381->6379/tcp   redis-slave-1
    2572ab587558        redis               "docker-entrypoint.s…"   3 seconds ago       Up 2 seconds        0.0.0.0:6382->6379/tcp   redis-slave-2
    f70a9d9809bc        redis               "docker-entrypoint.s…"   3 seconds ago       Up 2 seconds        0.0.0.0:6380->6379/tcp   redis-master
    

    也就是f70a9d9809bc

  2. 通過docker inspect f70a9d9809bc,拿到對(duì)應(yīng)容器的IP,在NetworkSettings -> Networks -> IPAddress字段。

然后把這個(gè)值給記錄下來,此處我的值為172.28.0.3

搭建Sentinel集群

sentinel目錄下的docker-compose.yml內(nèi)容如下。

version: '3'
services:
  sentinel1:
    image: redis
    container_name: redis-sentinel-1
    ports:
      - 26379:26379
    command: redis-sentinel /usr/local/etc/redis/sentinel.conf
    volumes:
      - ./sentinel1.conf:/usr/local/etc/redis/sentinel.conf
  sentinel2:
    image: redis
    container_name: redis-sentinel-2
    ports:
    - 26380:26379
    command: redis-sentinel /usr/local/etc/redis/sentinel.conf
    volumes:
      - ./sentinel2.conf:/usr/local/etc/redis/sentinel.conf
  sentinel3:
    image: redis
    container_name: redis-sentinel-3
    ports:
      - 26381:26379
    command: redis-sentinel /usr/local/etc/redis/sentinel.conf
    volumes:
      - ./sentinel3.conf:/usr/local/etc/redis/sentinel.conf
networks:
  default:
    external:
      name: redis_default

同樣在這里解釋一下命令

redis-sentinel 命令讓 redis 以 sentinel 的模式啟動(dòng),本質(zhì)上就是一個(gè)運(yùn)行在特殊模式的 redis 服務(wù)器。

和 redis-server 的區(qū)別在于,他們分別載入了不同的命令表,sentinel 中無法執(zhí)行各種redis中特有的 set get操作。

建立三份一模一樣的文件,分別命名為sentinel1.conf、sentinel2.conf和sentinel3.conf。其內(nèi)容如下:

port 26379
dir "/tmp"
sentinel deny-scripts-reconfig yes
sentinel monitor mymaster 172.28.0.3 6379 2
sentinel config-epoch mymaster 1
sentinel leader-epoch mymaster 1

可以看到,我們對(duì)于sentinel的配置文件中,sentinel monitor mymaster 172.28.0.3 6379 2表示讓它去監(jiān)聽名為mymaster的master節(jié)點(diǎn),注意此處的IP一定要是你自己master節(jié)點(diǎn)的IP,然后最后面的2就是我們之前提到的quorum

然后命令行進(jìn)入名為sentinel的目錄下,敲docker-compose up即可。至此,Sentinel集群便啟動(dòng)了起來。

手動(dòng)模擬master掛掉

然后我們需要手動(dòng)模擬master掛掉,來驗(yàn)證我們搭建的Sentinel集群是否可以正常的執(zhí)行故障轉(zhuǎn)移。

命令行進(jìn)入名為redis的目錄下,敲入如下命令。

docker-compose pause master

此時(shí)就會(huì)將master容器給暫停運(yùn)行,讓我們等待10秒之后,就可以看到sentinel這邊輸出了如下的日志。

redis-sentinel-2 | 1:X 07 Dec 2020 01:58:05.459 # +sdown master mymaster 172.28.0.3 6379
......
......
......
redis-sentinel-1 | 1:X 07 Dec 2020 01:58:06.932 # +switch-master mymaster 172.28.0.3 6379 172.28.0.2 6379

得得得,你干什么就甩一堆日志文件上來?湊字?jǐn)?shù)?你這樣鬼能看懂?

的確,光從日志文件一行一行的看,就算是我自己過兩周再來看,也是一臉懵逼。日志文件完整了描述了整個(gè)Sentinel集群從開始執(zhí)行故障轉(zhuǎn)移到最終執(zhí)行完成的所有細(xì)節(jié),但是在這里直接放出來不方便大家的理解。

所以為了讓大家能夠更加直觀的了解這個(gè)過程,我簡(jiǎn)單的把過程抽象了成了一張圖,大家看圖結(jié)合日志,應(yīng)該能夠更容易理解。

sentinel-process

里面關(guān)鍵的步驟步驟的相關(guān)解釋我也一并放入了圖片中。

最終的結(jié)果就是,master已經(jīng)從我們最開始的172.28.0.3切換到了172.28.0.2,后者則是原來的slave節(jié)點(diǎn)之一。此時(shí)我們也可以連接到172.28.0.2這個(gè)容器里去,通過命令來看一下其現(xiàn)在的情況。

role:master
connected_slaves:1
slave0:ip=172.28.0.4,port=6379,state=online,offset=18952,lag=0
master_replid:f0bf5d1c843ec3ab005c5ac2b864f7ffdc6a8217
master_replid2:72c43e1f9c05d4b08bea6bf9b2549997587e261c
master_repl_offset:18952
second_repl_offset:16351
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:18952

可以看到,現(xiàn)在的172.28.0.2這個(gè)節(jié)點(diǎn)的角色已經(jīng)變成了master,與其相連接的slave節(jié)點(diǎn)只有1個(gè),因?yàn)楝F(xiàn)在的原master還沒有啟動(dòng)起來,總共存活的只有2個(gè)實(shí)例。

原master重啟啟動(dòng)

接下來我們模擬原master重新啟動(dòng),來看一下會(huì)發(fā)什么什么。

還是通過命令行進(jìn)入到名為redis的本地目錄,通過docker-compose unpause master來模擬原master故障恢復(fù)之后的上線。同樣我們連接到原master的機(jī)器上去。

$ docker exec -it f70a9d9809bc1e924a5be0135888067ad3eb16552f9eaf82495e4c956b456cd9 /bin/sh; exit
# redis-cli
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:172.28.0.2
master_port:6379
master_link_status:up
......

master斷線重連之后,角色也變成了新的master(也就是172.28.0.2這個(gè)節(jié)點(diǎn))的一個(gè)slave。

然后我們也可以通過再看一下新master節(jié)點(diǎn)的replication情況作證。

# Replication
role:master
connected_slaves:2
slave0:ip=172.28.0.4,port=6379,state=online,offset=179800,lag=0
slave1:ip=172.28.0.3,port=6379,state=online,offset=179800,lag=1
......

原master短線重連之后,其connected_slaves變成了2,且原master172.28.0.3被清晰的標(biāo)注為了slave1,同樣與我們開篇和圖中所講的原理相符合。

好了以上就是本篇博客的全部?jī)?nèi)容了,歡迎微信搜索關(guān)注【SH的全棧筆記】,回復(fù)【隊(duì)列】獲取MQ學(xué)習(xí)資料,包含基礎(chǔ)概念解析和RocketMQ詳細(xì)的源碼解析,持續(xù)更新中。

如果你覺得這篇文章對(duì)你有幫助,還麻煩點(diǎn)個(gè)贊關(guān)個(gè)注分個(gè)享留個(gè)言

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,739評(píng)論 6 534
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,634評(píng)論 3 419
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,653評(píng)論 0 377
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,063評(píng)論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,835評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,235評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,315評(píng)論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,459評(píng)論 0 289
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,000評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,819評(píng)論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,004評(píng)論 1 370
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,560評(píng)論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,257評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,676評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,937評(píng)論 1 288
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,717評(píng)論 3 393
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,003評(píng)論 2 374

推薦閱讀更多精彩內(nèi)容