Redis哨兵原理,我忍你很久了!
原創(chuàng)【51CTO.com原創(chuàng)稿件】Redis 主從復(fù)制的作用中有這么一句話“主從復(fù)制是高可用的基石”,那什么是高可用呢?高可用就是減少系統(tǒng)不能提供的時(shí)間,也就是常聽到的以 6 個(gè) 9 為基準(zhǔn)。實(shí)現(xiàn)高可用必不可少的就是哨兵和集群。
本文主要圍繞如下幾個(gè)方面介紹哨兵機(jī)制:
- 什么是哨兵
- 哨兵的作用
- 如何配置哨兵
- 哨兵工作原理
- 總結(jié)
本文實(shí)現(xiàn)環(huán)境:
- centos 7.3
- redis 4.0
- redis 工作目錄 /usr/local/redis
- 在虛擬機(jī)進(jìn)行模擬操作
什么是哨兵
先簡(jiǎn)單說幾句我們?cè)谂渲弥鲝膹?fù)制時(shí)有一種情況就是主節(jié)點(diǎn)宕機(jī)了,誰來提供服務(wù)呢?
當(dāng)主節(jié)點(diǎn)宕機(jī)后主從復(fù)制就沒有存在的意義了,數(shù)據(jù)為王的時(shí)代沒有了數(shù)據(jù)何談什么高可用。
這個(gè)時(shí)候就橫空出世了一位老大哥名叫哨兵,老大哥說這個(gè)問題我來幫你們處理。
既然主節(jié)點(diǎn) master 作為老大不領(lǐng)你們玩了。我就從你們四個(gè)中間再挑選出來一位老大,然后你們跟著他玩。
等不帶你們玩的那個(gè)老大回來后他的身份就失效了,就不再是你們的老大了。他只能跟著我挑選出來的老大玩。
上邊這段對(duì)話過程就是我們配置哨兵的意義到底在哪,跟誰玩就是誰給誰數(shù)據(jù),知道了哨兵的作用我們就在繼續(xù)。
最后我們用專業(yè)術(shù)語來解釋一下什么是哨兵:
哨兵,英文名 Sentinel,是一個(gè)分布式系統(tǒng),用于對(duì)主從結(jié)構(gòu)中的每一臺(tái)服務(wù)器進(jìn)行監(jiān)控,當(dāng)主節(jié)點(diǎn)出現(xiàn)故障后通過投票機(jī)制來挑選新的主節(jié)點(diǎn),并且將所有的從節(jié)點(diǎn)連接到新的主節(jié)點(diǎn)上。
哨兵的作用
上文中我們談到的對(duì)話過程就是哨兵的作用之一:自動(dòng)故障轉(zhuǎn)移。
談到作用肯定就是這個(gè)哨兵到底在工作中到底干了什么事情。我們先用比較干巴的概念描述一下,然后在下文的工作原理會(huì)一一談到。
哨兵的三個(gè)作用:
- 監(jiān)控:監(jiān)控誰?支持主從結(jié)構(gòu)的工作一個(gè)是主節(jié)點(diǎn)一個(gè)是從節(jié)點(diǎn),那肯定就是監(jiān)控這倆個(gè)了。監(jiān)控主節(jié)點(diǎn)和從節(jié)點(diǎn)是否正常運(yùn)行;檢測(cè)主節(jié)點(diǎn)是否存活,主節(jié)點(diǎn)和從節(jié)點(diǎn)運(yùn)行情況。
- 通知:哨兵檢測(cè)的服務(wù)器出現(xiàn)問題時(shí),會(huì)向其他的哨兵發(fā)送通知,哨兵之間就相當(dāng)于一個(gè)微信群,每個(gè)哨兵發(fā)現(xiàn)的問題都會(huì)發(fā)在這個(gè)群里。
- 自動(dòng)轉(zhuǎn)移故障:當(dāng)檢測(cè)到主節(jié)點(diǎn)宕機(jī)后,斷開與宕機(jī)主節(jié)點(diǎn)連接的所有從節(jié)點(diǎn),在從節(jié)點(diǎn)中選取一個(gè)作為主節(jié)點(diǎn),然后將其他的從節(jié)點(diǎn)連接到這個(gè)最新主節(jié)點(diǎn)的上。并且告知客戶端最新的服務(wù)器地址。
這里有一個(gè)注意點(diǎn),哨兵也是一臺(tái) Redis 服務(wù)器,只是不對(duì)外提供任何服務(wù)。配置哨兵時(shí)配置為單數(shù)。
那么為什么配置哨兵服務(wù)器的數(shù)量為單數(shù)呢?帶著這個(gè)疑問你會(huì)在下文看到你想要的答案。
如何配置哨兵
準(zhǔn)備工作
我們開始配置哨兵,開啟八個(gè)客戶端,三個(gè)哨兵、一個(gè)主節(jié)點(diǎn)、倆個(gè)從節(jié)點(diǎn)、一個(gè)主節(jié)點(diǎn)客戶端、一個(gè)從節(jié)點(diǎn)客戶端。
sentinel.conf 配置解讀
哨兵使用的配置文件是 sentinel.conf,如下圖:
我們來對(duì) sentinel.conf 配置信息進(jìn)行解讀:
但是大多數(shù)都是注釋,這里給大家提供一個(gè)命令來過濾這些無用信息:
- cat sentinel.conf | grep -v '#' | grep -v '^$'
①port 26379:對(duì)外服務(wù)端口號(hào)。
②dir /tmp:存儲(chǔ)哨兵的工作信息。
③sentinel monitor mymaster 127.0.0.1 6379 2:監(jiān)控的是誰,名字可以自定義,后邊的 2 代表的是,如果有倆個(gè)哨兵判斷這個(gè)主節(jié)點(diǎn)掛了那這個(gè)主節(jié)點(diǎn)就掛了,通常設(shè)置為哨兵個(gè)數(shù)一半加一。
④sentinel down-after-milliseconds mymaster 30000:哨兵連接主節(jié)點(diǎn)多長(zhǎng)時(shí)間沒有響應(yīng)就代表掛了。后邊 30000 是毫秒,也就是 30 秒。
⑤sentinel parallel-syncs mymaster 1:這個(gè)配置項(xiàng)是指在故障轉(zhuǎn)移時(shí),最多有多少個(gè)從節(jié)點(diǎn)對(duì)新的主節(jié)點(diǎn)進(jìn)行同步。
這個(gè)值越小完成故障轉(zhuǎn)移的時(shí)間就越長(zhǎng),這個(gè)值越大就意味著越 多的從節(jié)點(diǎn)因?yàn)橥綌?shù)據(jù)而不可用。
⑥sentinel failover-timeout mymaster 180000:在進(jìn)行同步的過程中,多長(zhǎng)時(shí)間完成算有效,系統(tǒng)默認(rèn)值是 3 分鐘。
開始配置
使用命令 cat sentinel.conf | grep -v '#' | grep -v '^$' > ./data/sentinel-26379.conf 把 sentinel.conf 過濾后的信息移到 /usr/local/redis/conf 下。
然后打開 sentinel-26379.conf 修改信息存放目錄:
再快速的復(fù)制兩個(gè)哨兵配置文件,端口為 26380 和 26381:
- sed 's/26379/26381/g' sentinel-26379.conf > sentinel-26381.conf
測(cè)試主從復(fù)制處于正常工作狀態(tài),啟動(dòng)三臺(tái) redis 服務(wù)器,端口分別為 6379、6380、6381:
查看主節(jié)點(diǎn)信息,是有倆臺(tái)從節(jié)點(diǎn)在連接著,端口分別為 6380、6381。
這里有一個(gè)小小的點(diǎn)就是 lag 怎么一個(gè)是 1 一個(gè)是 0 呢?lag 是延遲時(shí)間,我這里是本地測(cè)試所以會(huì)出現(xiàn) 0 的情況,使用云服務(wù)器是很少出現(xiàn)的。
lag 的值為 0 和 1 都屬于正常。
測(cè)試主節(jié)點(diǎn)添加一個(gè) hash 值,hset kaka name kaka:
分別從 slave1 和 slave2 獲取 kaka 的值,檢測(cè)主從復(fù)制是否正常運(yùn)行。
經(jīng)過測(cè)試我們的主從結(jié)構(gòu)是正常運(yùn)行的,如下圖:
啟動(dòng)一個(gè)哨兵 redis-sentinel 26379-sentinel.conf:
連接 26379 哨兵,主要是最后一行,監(jiān)控的主節(jié)點(diǎn)名為 mymaster,狀態(tài)正常,從節(jié)點(diǎn)有倆個(gè),哨兵數(shù)量為 1 個(gè)。
再來查看一下 26379 的哨兵配置信息,這個(gè)時(shí)候已經(jīng)改動(dòng)了:
在啟動(dòng)一個(gè) 26380 的哨兵,redis-sentinel 26380-sentinel.conf,這里注意一下最后一行多了一條信息,這個(gè) id 就是我們 26379 配置文件新增的 id。
然后我們來到哨兵 26379 的客戶端,同樣也是新增的 26380 哨兵的 id:
這個(gè)時(shí)候我們?cè)俨榭匆幌?26379 哨兵的配置文件,第一次查看配置文件是沒有配置 26380 哨兵的,第二次查看時(shí)配置了 26380 哨兵后添加的信息。
最后我們需要把哨兵客戶端 3 啟動(dòng)起來,端口號(hào)為 26381。啟動(dòng)起來之后,我們的配置信息和服務(wù)端的信息也會(huì)改動(dòng),添加哨兵 26380 有的信息,哨兵 26381 也會(huì)有。
直到這里我們對(duì)哨兵的配置就結(jié)束了,接下來我們把主節(jié)點(diǎn) Master 給宕掉。
等待 30 秒后我們來到 26379 哨兵的客戶端,這里新增了一些信息,那么這些信息都做了什么呢?讓我們細(xì)細(xì)道來。
這里邊的信息我們先需要知道幾個(gè):
①+sdown:這個(gè)信息后是指三個(gè)哨兵里邊有一個(gè)認(rèn)為主節(jié)點(diǎn)宕機(jī)了。
②+odown:這個(gè)信息是指其他倆個(gè)哨兵去連接了一下主節(jié)點(diǎn),發(fā)現(xiàn)確實(shí)是主節(jié)點(diǎn)宕機(jī)了,然后發(fā)起了一輪投票。這里使用的是 redis 4.0,版本之間這塊信息有點(diǎn)差異。
③+switch-master mymaster 127.0.0.1 6379 127.0.0.1 6380:直到這里是哨兵發(fā)起投票的結(jié)果,推選端口為 6380 的 redis 為主節(jié)點(diǎn)。
④+slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380:這里就把端口為 6381 與 6379 和新的主節(jié)點(diǎn) 6380 做了一個(gè)連接。
⑤+sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380:最后一句是端口為 6379 的還是沒有上線,于是給踢下線。
當(dāng)我們?cè)谥匦掳?6379 的 redis 服務(wù)器上線后,就可以看到哨兵服務(wù)端響應(yīng)了倆句。一句是去除 6379 的下線。最后一句就是重連 6379 到新的主節(jié)點(diǎn)上。
這個(gè)時(shí)候主節(jié)點(diǎn)就是 6380 了,在 6380 的 redis 客戶端設(shè)置值,檢測(cè)主從復(fù)制是否正常工作。
在新的主節(jié)點(diǎn) 6380 添加 list 類型:
在 6379 和 6381 獲取這個(gè)值,至此,我們的哨兵模式就配置完成了。
哨兵工作原理
配置完哨兵后,就需要對(duì)其工作原理進(jìn)行解析了,只有知道其工作流程,才能對(duì)哨兵有更好的理解。
本文講解原理沒有那么干巴!讓你可以把一篇技術(shù)文章當(dāng)故事去看。
進(jìn)入正題,哨兵作用是監(jiān)控、通知、故障轉(zhuǎn)移。那么工作原理也是圍繞這三點(diǎn)來講的。
監(jiān)控工作流程
監(jiān)控工作流程如下:
①哨兵發(fā)送 info 指令,并且保存所有哨兵狀態(tài),主節(jié)點(diǎn)和從節(jié)點(diǎn)的信息。
②主節(jié)點(diǎn)會(huì)記錄 redis 實(shí)例的信息,主節(jié)點(diǎn)記錄的信息跟哨兵記錄的信息看起來是一樣的,實(shí)際上還是有點(diǎn)區(qū)別。
③哨兵會(huì)根據(jù)在主節(jié)點(diǎn)拿到的從節(jié)點(diǎn)信息,給對(duì)應(yīng)的從節(jié)點(diǎn)也發(fā)送 info 指令。
④接著哨兵 2 來了,同樣的也會(huì)給主節(jié)點(diǎn)發(fā)送 info 指令,并且建立 cmd 連接。
⑤這個(gè)時(shí)候哨兵 2 也會(huì)保存跟哨兵 1 一樣的信息,只不過是保存的哨兵信息是 2 個(gè)。
⑥這個(gè)時(shí)候?yàn)榱嗣總€(gè)哨兵的信息都一致它們之間建立了一個(gè)發(fā)布訂閱。為了哨兵之間的信息長(zhǎng)期對(duì)稱它們之間也會(huì)互發(fā) ping 命令。
⑦當(dāng)再來一個(gè)哨兵 3 時(shí),也會(huì)做同樣的事情,給主節(jié)點(diǎn)和從節(jié)點(diǎn)發(fā)送 info。并且跟哨兵 1 和哨兵 2 建立連接。
通知工作流程
sentinel 會(huì)給主從的所有節(jié)點(diǎn)發(fā)送命令獲取其狀態(tài),并且會(huì)把信息發(fā)布到哨兵的訂閱里。
故障轉(zhuǎn)移原理
哨兵會(huì)一直給主節(jié)點(diǎn)發(fā)送 publish sentinel:hello,直到哨兵報(bào)出 sdown,這個(gè)詞這會(huì)是有不是有點(diǎn)熟悉了。沒錯(cuò)就是我們上文中把主節(jié)點(diǎn)斷開后哨兵服務(wù)端報(bào)出的信息。
哨兵報(bào)出主節(jié)點(diǎn) sdown 后還沒有完,哨兵還會(huì)往內(nèi)網(wǎng)里發(fā)布消息說明這個(gè)主節(jié)點(diǎn)掛了。發(fā)送的指令是 sentinel is-master-down-by-address-port。
其余的哨兵接收到指令后,主節(jié)點(diǎn)掛了嗎?讓我去看看到底掛沒掛。發(fā)送的信息也是 hello。
其余的哨兵也會(huì)發(fā)送他們收到的信息并且發(fā)送指令 sentinel is-master-down-by-address-port 到自己的內(nèi)網(wǎng),確認(rèn)一下第一個(gè)發(fā)送 sentinel is-master-down-by-address-port 的哨兵說你說的對(duì),這個(gè)家伙確實(shí)掛了。
當(dāng)所有人都認(rèn)為主節(jié)點(diǎn)掛了后就會(huì)修改其狀態(tài)為 odown。當(dāng)一個(gè)哨兵認(rèn)為主節(jié)點(diǎn)掛了標(biāo)記的是 sdown,當(dāng)半數(shù)哨兵都認(rèn)為掛了其標(biāo)記的狀態(tài)是 odown。這也就是配置哨兵為什么配置單數(shù)的原因。
對(duì)于一個(gè)哨兵認(rèn)為主節(jié)點(diǎn)掛了稱之為主觀下線,半數(shù)哨兵認(rèn)為主節(jié)點(diǎn)掛了稱之為客官下線。
一旦被認(rèn)為主節(jié)點(diǎn)客官下線后,哨兵就會(huì)進(jìn)行下一步操作:
這時(shí)哨兵已經(jīng)檢測(cè)到問題所在了,那么到底是那個(gè)哨兵去負(fù)責(zé)推選新的主節(jié)點(diǎn)呢!不能是張三也去,李四也去,王五也去,這樣就亂套了、于是就需要在所有的哨兵里選出領(lǐng)頭的,那么是如何選的呢!請(qǐng)看下圖。
這個(gè)時(shí)候,五個(gè) sentinel 就在一起開會(huì)了,所有的哨兵都在一個(gè)內(nèi)網(wǎng)中,然后他們會(huì)做一件事情就是五個(gè) sentinel 會(huì)同時(shí)發(fā)送指令 sentinel is-master-down-by-address-port 并且攜帶上自己競(jìng)選次數(shù)和 runid。
每個(gè) sentinel 既是參選者也是投票者,每個(gè) sentinel 都有一票,信封就代表自己的投票權(quán)。
當(dāng) sentinel1 和 sentinel4 同時(shí)把指令發(fā)送到群里準(zhǔn)備競(jìng)選時(shí),sentinel2 這個(gè)時(shí)候就說我先接到誰的指令就把票投給誰。
假如 sentinel1 發(fā)的早,那么 sentinel2 的票就會(huì)投給 sentinel1。
按照這樣的規(guī)則一直發(fā)起投票直到有一個(gè) sentinel 的票數(shù)為總 sentinel 數(shù)量的一半之多。
假設(shè)說是 sentinel1 的票數(shù)滿足總哨兵數(shù)量的一半之多后,sentinel1 就會(huì)當(dāng)選。這個(gè)時(shí)候就進(jìn)行到了下一個(gè)階段。
在上邊哨兵已經(jīng)選出了 sentinel1 為代表去所有的從節(jié)點(diǎn)找出一個(gè)作為主節(jié)點(diǎn)。這個(gè)挑選主節(jié)點(diǎn)不是隨便拿一個(gè)是有一定的規(guī)則的。
先把不在線的干掉:
響應(yīng)慢的干掉,sentinel 會(huì)給所有的 redis 發(fā)送信息,響應(yīng)速度慢的就會(huì)被干掉。
與原主節(jié)點(diǎn)斷開時(shí)間最久的干掉,這里由于演示不夠用了,所有新增了一個(gè) slave5,沒有任何意義哈!
以上三個(gè)點(diǎn)都判斷結(jié)束后還有 salve4 和 slave5,就會(huì)根據(jù)優(yōu)先原則來進(jìn)行篩選:
- 首先會(huì)根據(jù)優(yōu)先級(jí),如果優(yōu)先級(jí)一樣在進(jìn)行其他判斷。
- 判斷 offset 偏移量,判斷數(shù)據(jù)同步性,假如說 slave4 的 offset 為 90,slave5 偏移量為 100。
那么哨兵就會(huì)認(rèn)為 slave4 的網(wǎng)絡(luò)是不是有問題,于是就會(huì)選 slave5 為新的主節(jié)點(diǎn)。那如果說是 slave4 和 slave5 的 offset 相同呢!還有最后一個(gè)判斷。
- 最后一步就是判斷 runid 了,也就是職場(chǎng)中的論資排輩了,也就說根據(jù) runid 的創(chuàng)建時(shí)間來判斷,時(shí)間早的上位。
選出新的主節(jié)點(diǎn)后就要對(duì)所有的節(jié)點(diǎn)發(fā)送指令了。
總結(jié)
關(guān)于哨兵的所有知識(shí)點(diǎn)就已經(jīng)說完了,本文最重要的就是哨兵的工作原理了。
我們?cè)诤?jiǎn)單的梳理一下其工作原理:
- 首先進(jìn)行監(jiān)控,并且所有的哨兵同步信息。
- 哨兵向訂閱里邊發(fā)布信息。
- 故障轉(zhuǎn)移:哨兵發(fā)現(xiàn)主節(jié)點(diǎn)下線→哨兵開啟投票競(jìng)選負(fù)責(zé)人→由負(fù)責(zé)人推選新的主節(jié)點(diǎn)→新的主節(jié)點(diǎn)斷開原主節(jié)點(diǎn),并且其他的從節(jié)點(diǎn)連接新的主節(jié)點(diǎn),原主節(jié)點(diǎn)上線后作為從節(jié)點(diǎn)連接。
以上就是筆者對(duì)哨兵的理解,如果錯(cuò)誤歡迎指出,以便及時(shí)改正。
作者:咔咔
簡(jiǎn)介:從業(yè)三年,從搬磚一樣的生活方式換成了現(xiàn)在有“單”而居的日子。當(dāng)然這個(gè)單不是單身的單!雖然極盡苛刻的技術(shù)學(xué)習(xí)但也遠(yuǎn)不及客戶千奇百怪的要求。進(jìn)入了朝九晚六,雖然躲過了風(fēng)吹日曬,但是仍然很享受那些熬得只剩下黑眼圈的日子。堅(jiān)持學(xué)習(xí)、堅(jiān)持寫博、堅(jiān)持分享是咔咔從業(yè)以來一直所秉持的信念。希望在諾大互聯(lián)網(wǎng)中咔咔的文章能帶給你一絲絲幫助。
【51CTO原創(chuàng)稿件,合作站點(diǎn)轉(zhuǎn)載請(qǐng)注明原文作者和出處為51CTO.com】