[TOC]
1 哨兵模式能做什么?
在上一篇文章中介紹的redis主從復(fù)制(http://blog.csdn.net/hylexus/article/details/69360701)雖然可以達(dá)到主從復(fù)制的目的俐银。
但是并沒(méi)有考慮高可用船响,也就是說(shuō):當(dāng)主機(jī)宕機(jī)后碎浇,備機(jī)不能及時(shí)自動(dòng)頂替主機(jī)
讥裤,這當(dāng)然不行的宅静。
這里介紹的redis的哨兵模式能夠在后臺(tái)監(jiān)控主機(jī)是否發(fā)生故障,如果發(fā)生故障了涌乳,可以及時(shí)根據(jù)投票數(shù)自動(dòng)將從庫(kù)轉(zhuǎn)換為主庫(kù)蜻懦。從而在一定意義上達(dá)到高可用
。
2 哨兵模式相關(guān)的知識(shí)點(diǎn)
2.1 哨兵提供的功能
- 監(jiān)控(monitoring)
- 定期檢查監(jiān)控的master和slave的狀態(tài)
- 通知(notification)
- 當(dāng)檢測(cè)到故障時(shí)可以發(fā)送通知
- 自動(dòng)故障轉(zhuǎn)移(auto-failover)
- 檢測(cè)到master不能工作時(shí),可以將master的下屬slave中的一個(gè)升級(jí)為master
- 客戶端連接已經(jīng)不可用的master時(shí),想客戶端返回新的master地址
- 自動(dòng)發(fā)現(xiàn)其他sentinel和從服務(wù)器
- Sentinel 可以通過(guò)
發(fā)布與訂閱功
能來(lái)自動(dòng)發(fā)現(xiàn)
正在監(jiān)視相同主服務(wù)器的其他 Sentinel - Sentinel 可以通過(guò)詢問(wèn)主服務(wù)器來(lái)獲得
所有從服務(wù)器的信息
- Sentinel 可以通過(guò)
- sentinel配置自動(dòng)持久化
- 當(dāng) Sentinel 接收到一個(gè)新的配置夕晓, 或者當(dāng)領(lǐng)頭 Sentinel 為主服務(wù)器創(chuàng)建一個(gè)新的配置時(shí)宛乃, 這個(gè)配置會(huì)與配置紀(jì)元一起被保存到磁盤(pán)里面
- 停止和重啟 Sentinel 進(jìn)程都是安全的
2.2 主觀下線和客觀下線
sentinel會(huì)定時(shí)
向其所監(jiān)控的服務(wù)器發(fā)送ping命令
以詢問(wèn)服務(wù)器是否還正常地活著
.
如果服務(wù)器的回應(yīng)是有效回復(fù),則認(rèn)為該服務(wù)器還正常地活著
.有效回復(fù)有以下三類:
- 返回
+PONG
- 返回
-LOADING
- 返回
-MASTERDOWN
換言之:如果服務(wù)器的回應(yīng)不是以上三種之一,或者
在指定的時(shí)間內(nèi)沒(méi)有回復(fù),都將被認(rèn)為是無(wú)效的回復(fù).
另外需要注意的是:
如果 master-down-after-milliseconds
選項(xiàng)的值為 60000 ms
(60 s
)征炼, 那么即使服務(wù)器在第59 s
時(shí)返回至少一次有效回復(fù)析既, 這個(gè)服務(wù)器就仍然會(huì)被認(rèn)為是處于正常狀態(tài)的。
主觀下線和客觀下線
- 主觀下線(Subjectively Down==sdown):?jiǎn)蝹€(gè) Sentinel 實(shí)例對(duì)服務(wù)器做出的下線判斷
- 客觀下線(Objectively Down==odown):多個(gè) Sentinel 實(shí)例都對(duì)某服務(wù)器得出
sdown
的判斷
2.3 哨兵配置文件
配置文件中的選項(xiàng)
- down-after-milliseconds : 多少
毫秒內(nèi)
得不到服務(wù)器的回應(yīng)時(shí)sentinel可以認(rèn)為該服務(wù)器已經(jīng)下線 - parallel-syncs : 在完成故障轉(zhuǎn)移時(shí)最多可以有幾個(gè)slave從新的master同步數(shù)據(jù)
- myid :sentinel自身的ID,和zookeeper集群中的myid類似
- port :指定sentinel的端口(默認(rèn)是redis示例端口前加個(gè)2比如26379)
一點(diǎn)說(shuō)明
其實(shí)你可以指定一個(gè)最小化的配置,其他的配置項(xiàng)redis會(huì)幫你生成谆奥。
比如渡贾,你可以只指定sentinel monitor <name> <host> <port> <count>
.其他項(xiàng)都會(huì)自動(dòng)生成.
當(dāng)然,你最好將保護(hù)模式關(guān)閉雄右。
配置文件示例
# 哨兵自己的id,和zookeeper中的myid類似
sentinel myid 37a94ac96520c311ca2976d56e716e3bbb4e9111
# 關(guān)閉保護(hù)模式(和redis.conf中的配置類似)
protected-mode no
# 監(jiān)控名為master-test的集群
sentinel monitor master-test 192.168.1.131 6379 2
# 多少毫秒內(nèi)sentinel可以認(rèn)為他監(jiān)控的對(duì)象已經(jīng)斷線
sentinel down-after-milliseconds master-test 10000
# 故障轉(zhuǎn)移的超時(shí)時(shí)間
sentinel failover-timeout master-test 10000
2.4 故障轉(zhuǎn)移過(guò)程
- 檢測(cè)到
master
已經(jīng)進(jìn)入sdown
(客觀下線)狀態(tài) - 對(duì)
當(dāng)前紀(jì)元
進(jìn)行自增,并嘗試成為leader-sentinel
- 沒(méi)能成為
leader-sentinel
- 在設(shè)定的
failover-timeout
的兩倍之后纺讲, 重新嘗試
- 在設(shè)定的
- 成功成為
leader-sentinel
- 選出一個(gè)
slave
擂仍,并升級(jí)為master
- 通過(guò)發(fā)布與訂閱功能, 將更新后的配置傳播給所有其他 Sentinel 熬甚, 其他 Sentinel 對(duì)它們自己的配置進(jìn)行更新
- 向已下線主服務(wù)器的從服務(wù)器發(fā)送
SLAVEOF
命令逢渔, 讓它們?nèi)?fù)制新的主服務(wù)器 - 當(dāng)所有從服務(wù)器都已經(jīng)開(kāi)始復(fù)制新的主服務(wù)器時(shí),
leader-sentinel
終止這次故障轉(zhuǎn)移操作
- 選出一個(gè)
- 沒(méi)能成為
3 配置示例
3.1 說(shuō)明
- 為方便操作此處用主機(jī)名代替IP操作
- 整個(gè)結(jié)構(gòu)還是上一篇文章中的一主二從
- 三個(gè)redis分別位于三臺(tái)主機(jī)上
3.2 配置
- 哨兵配置文件(三臺(tái)主機(jī)是一致的)
sentinel monitor master-test h1 6379 2
protected-mode no
# 以下兩項(xiàng)不是必須的(此處只是為了較快的看到變化才縮短了時(shí)間配置)
sentinel down-after-milliseconds master-test 10000
sentinel failover-timeout master-test 10000
3.3 啟動(dòng)
- 啟動(dòng)redis實(shí)例
# 啟動(dòng)master
[root@h1 redis]$ redis-server redis.conf
# 啟動(dòng)slave h1
[root@h2 redis]$ redis-server redis.conf --slaveof h1 6379
# 啟動(dòng)slave h2
[root@h3 redis]$ redis-server redis.conf --slaveof h1 6379
- 啟動(dòng)sentinel實(shí)例(三臺(tái)機(jī)器一樣的命令)
[root@h1 redis]$ redis-sentinel sentinel.conf
此時(shí)可以看看redis自動(dòng)生成的哨兵配置文件內(nèi)容:
[root@h1 redis]$ cat sentinel.conf
port 26379
sentinel myid 37a94ac96520c311ca2976d56e716e3bbb4e9111
protected-mode no
# Generated by CONFIG REWRITE
dir "/data/redis"
sentinel monitor master-test 192.168.1.131 6379 2
sentinel down-after-milliseconds master-test 10000
sentinel failover-timeout master-test 10000
sentinel config-epoch master-test 4
sentinel leader-epoch master-test 4
sentinel known-slave master-test 192.168.1.132 6379
sentinel known-slave master-test 192.168.1.133 6379
sentinel known-sentinel master-test 192.168.1.132 26379 ac72dd0def3cf1ee47bab9dba9d4454693a2c222
sentinel known-sentinel master-test 192.168.1.133 26379 3dcc2ef2b3aff48d61afb0ae041ce08e59e4b333
sentinel current-epoch 4
- sentinel的日志輸出
# 當(dāng)前sentinel的ID
Sentinel ID is 37a94ac96520c311ca2976d56e716e3bbb4e9111
# 當(dāng)前監(jiān)控的master
+monitor master master-test 192.168.1.133 6379 quorum 2
# 檢測(cè)到了其他的sentinel
+sentinel sentinel ac72dd0def3cf1ee47bab9dba9d4454693a2c222 192.168.1.132 26379 @ master-test 192.168.1.133 6379
# 檢測(cè)到了其他的sentinel
+sentinel sentinel 3dcc2ef2b3aff48d61afb0ae041ce08e59e4b333 192.168.1.133 26379 @ master-test 192.168.1.133 6379
# 檢測(cè)到的master的下屬slave
+slave slave 192.168.1.132:6379 192.168.1.132 6379 @ master-test 192.168.1.131 6379
+slave slave 192.168.1.133:6379 192.168.1.133 6379 @ master-test 192.168.1.131 6379
3.4 測(cè)試
- 手動(dòng)停止主機(jī)h1
[root@h1 redis]$ redis-cli shutdown
此時(shí)看看h1上哨兵的日志輸出:
# h1主觀下線
+sdown master master-test 192.168.1.131 6379
# h1客觀下線
+odown master master-test 192.168.1.131 6379 #quorum 3/2
# 開(kāi)始嘗試故障轉(zhuǎn)移
+try-failover master master-test 192.168.1.131 6379
………………
# 最終將h2選為新的master
+switch-master master-test 192.168.1.131 6379 192.168.1.132 6379
- 再次啟動(dòng)h1
[root@h1 redis]$ redis-server redis.conf
此時(shí)可以看到類似如下輸出:
# h1的主觀下線狀態(tài)被取消
-sdown slave 192.168.1.131:6379 192.168.1.131 6379 @ master-test 192.168.1.132 6379
# 原來(lái)的master(h1)回來(lái)后被轉(zhuǎn)成了當(dāng)前master(h2)的slave
+convert-to-slave slave 192.168.1.131:6379 192.168.1.131 6379 @ master-test 192.168.1.132 6379
- 同時(shí)還有一點(diǎn)更牛逼的是:
# 此時(shí)查看h1上redis的配置文件中關(guān)于slave的配置已經(jīng)被自動(dòng)修改了
[root@h1 redis]$ cat redis.conf | grep slaveof
# Master-Slave replication. Use slaveof to make a Redis instance a copy of
# slaveof <masterip> <masterport>
# slaveof h1 6379
slaveof 192.168.1.132 6379 # *****這個(gè)是自動(dòng)修改過(guò)的****
[root@h1 redis]$
# h3的配置文件也被修改過(guò)了
[root@h3 redis]$ cat redis.conf | grep slaveof
# Master-Slave replication. Use slaveof to make a Redis instance a copy of
# slaveof <masterip> <masterport>
slaveof 192.168.1.132 6379
[root@h3 redis]$
3.5 sentinel日志輸出
以下內(nèi)容來(lái)自:http://www.redis.cn/topics/sentinel.html
- +reset-master :主服務(wù)器已被重置
- +slave :一個(gè)新的從服務(wù)器已經(jīng)被 Sentinel 識(shí)別并關(guān)聯(lián)。
- +failover-state-reconf-slaves :故障轉(zhuǎn)移狀態(tài)切換到了 reconf-slaves 狀態(tài)乡括。
- +failover-state-select-slave :故障轉(zhuǎn)移操作現(xiàn)在處于 select-slave 狀態(tài) —— Sentinel 正在尋找可以升級(jí)為主服務(wù)器的從服務(wù)器肃廓。
- failover-state-send-slaveof-noone :Sentinel 正在將指定的從服務(wù)器升級(jí)為主服務(wù)器,等待升級(jí)功能完成诲泌。
- failover-end-for-timeout :故障轉(zhuǎn)移因?yàn)槌瑫r(shí)而中止
- failover-end :故障轉(zhuǎn)移操作順利完成盲赊。所有從服務(wù)器都開(kāi)始復(fù)制新的主服務(wù)器了
- no-good-slave :Sentinel 操作未能找到適合進(jìn)行升級(jí)的從服務(wù)器。Sentinel 會(huì)在一段時(shí)間之后再次嘗試尋找合適的從服務(wù)器來(lái)進(jìn)行升級(jí)敷扫,又或者直接放棄執(zhí)行故障轉(zhuǎn)移操作哀蘑。
- +sentinel :一個(gè)監(jiān)視給定主服務(wù)器的新 Sentinel 已經(jīng)被識(shí)別并添加。
- +sdown :給定的實(shí)例現(xiàn)在處于主觀下線狀態(tài)葵第。
- -sdown :給定的實(shí)例已經(jīng)不再處于主觀下線狀態(tài)绘迁。
- +odown :給定的實(shí)例現(xiàn)在處于客觀下線狀態(tài)。
- -odown :給定的實(shí)例已經(jīng)不再處于客觀下線狀態(tài)卒密。
總結(jié)
主從復(fù)制+哨兵可以解決高可用和部分高性能缀台。
之所以說(shuō)是部分高性能是因?yàn)橹鲝膹?fù)制可以提供讀的性能,但是寫(xiě)操作依然是單點(diǎn)master負(fù)責(zé)哮奇。
后續(xù)的有關(guān)redis集群的文章將介紹這方面的內(nèi)容膛腐。