上一篇文章我們簡(jiǎn)單介紹了redis api 的使用方式司抱,本節(jié)的內(nèi)容,我們講一下他是如何保證高可用的燎竖。
測(cè)試版本是redis-3.2.11,從官網(wǎng)拉去到源碼后址芯,進(jìn)行編譯make,就會(huì)在src目錄下看到很多可執(zhí)行文件,例如redis-server,redis-cli,redis-sentinel等大家耳熟能詳?shù)摹?/p>
首先我們解釋一下主從的區(qū)別:主對(duì)于數(shù)據(jù)可讀可寫(xiě)诚纸。從默認(rèn)是只讀不寫(xiě)的撰筷。當(dāng)從連接上主時(shí),主會(huì)將數(shù)據(jù)同步到從上畦徘。詳細(xì)的內(nèi)容我們可以參考一下Redis主從同步原理-SYNC這篇文章講的還是很詳細(xì)的毕籽。
哨兵:當(dāng)主掛掉,哨兵可以通過(guò)選舉從從服務(wù)器中選擇一臺(tái)作為主井辆,提供高可用的方案关筒。注意當(dāng)原來(lái)的主恢復(fù)時(shí),也將成為現(xiàn)在主的從服務(wù)器杯缺。
概念解釋完了蒸播,我們來(lái)搭建環(huán)境。首先我們搭建的是主從。從最基本的一主一從開(kāi)始袍榆。
主的配置相較于默認(rèn)的配置文件修改的點(diǎn)胀屿,主要修改的是存放數(shù)據(jù)的目錄而已
bind 127.0.0.1
port 6379
pidfile "/Users/olifer/middle/redis/master/redis_6379.pid"
dir "/Users/olifer/middle/redis/master"
配置好了我們啟動(dòng)服務(wù)redis-server redis.conf , 如果看到下面的文字,說(shuō)明啟動(dòng)成功
783:M 02 Dec 19:19:39.829 # Server started, Redis version 3.2.11
783:M 02 Dec 19:19:39.829 * The server is now ready to accept connections on port 6379
從的配置也相對(duì)較為簡(jiǎn)單,端口改一下6380,最為主要的是配置slaveof包雀,指明他的主是誰(shuí)
bind 127.0.0.1
port 6380
pidfile "/Users/olifer/middle/redis/slave/redis_6380.pid"
dir "/Users/olifer/middle/redis/slave1"
slaveof 127.0.0.1 6379
配置好了我們啟動(dòng)服務(wù)redis-server redis.conf , 如果看到下面的文字,說(shuō)明啟動(dòng)成功
900:S 02 Dec 19:22:16.682 # Server started, Redis version 3.2.11
900:S 02 Dec 19:22:16.682 * The server is now ready to accept connections on port 6380
900:S 02 Dec 19:22:16.684 * Connecting to MASTER 127.0.0.1:6379
900:S 02 Dec 19:22:16.684 * MASTER <-> SLAVE sync started
通過(guò)slave的日志我們可以看出宿崭,啟動(dòng)成功,暴露端口為6380才写,并且連接上了自己的主6379葡兑,并且開(kāi)始了同步數(shù)據(jù)。
這時(shí)候我們可以看一下主的日志琅摩,同樣也能得到類似的信息,從主的日志可以看出铁孵,從確實(shí)連接上了主,并且愛(ài)是同步數(shù)據(jù)到從服務(wù)器房资,這個(gè)數(shù)據(jù)同步的過(guò)程我們會(huì)在下一篇文章中講述蜕劝。
783:M 02 Dec 19:22:16.685 * Slave 127.0.0.1:6380 asks for synchronization
783:M 02 Dec 19:22:16.685 * Full resync requested by slave 127.0.0.1:6380
783:M 02 Dec 19:22:16.685 * Starting BGSAVE for SYNC with target: disk
783:M 02 Dec 19:22:16.685 * Background saving started by pid 901
901:C 02 Dec 19:22:16.685 * DB saved on disk
783:M 02 Dec 19:22:16.760 * Background saving terminated with success
783:M 02 Dec 19:22:16.761 * Synchronization with slave 127.0.0.1:6380 succeeded
目前為止我們一個(gè)redis的主從就這么搭建好了,是不是超級(jí)簡(jiǎn)單轰异,搭建好了岖沛,我們就需要驗(yàn)證功能了。我們使用redis-cli連接到主上搭独,也就是6379婴削。當(dāng)然你也可以不用指定-p,因?yàn)槟J(rèn)的就是6379牙肝,這樣就可以進(jìn)入到redis shell的操作界面唉俗。我們簡(jiǎn)單的set一個(gè)值
redis-cli -p 6379
127.0.0.1:6379> set name olifer
OK
這時(shí)候我們驗(yàn)證一下從服務(wù)器的數(shù)據(jù)有沒(méi)有同步過(guò)來(lái)。
redis-cli -p 6380
127.0.0.1:6380> get name
"olifer"
和我們預(yù)想的是一致的配椭,我們從從的服務(wù)器上可以獲取到主的數(shù)據(jù)虫溜,更為確切的說(shuō),是主從數(shù)據(jù)進(jìn)行了準(zhǔn)實(shí)時(shí)的同步股缸,所以可以從從服務(wù)器上獲取到數(shù)據(jù)衡楞。
我們可以往從服務(wù)器上設(shè)置值嗎?實(shí)踐是檢驗(yàn)真理的唯一的方式敦姻,試一下
127.0.0.1:6380> set age 123
(error) READONLY You can't write against a read only slave.
發(fā)現(xiàn)報(bào)錯(cuò)了瘾境,slave默認(rèn)情況下是不能寫(xiě)數(shù)據(jù),只能讀取數(shù)據(jù)镰惦。當(dāng)然這個(gè)也是可以設(shè)置的迷守,在從的配置文件中有這個(gè)一個(gè)配置
slave-read-only yes
從名字我們就看出來(lái)他是只讀的,如果我們想slave也可以寫(xiě)陨献,我們可以修改此配置為no,之后我們重啟一下盒犹,看結(jié)果就可以了。
127.0.0.1:6380> set age 123
OK
所以一些有用的配置大家還是屬性一下吧。
現(xiàn)在大家思考一個(gè)問(wèn)題急膀,主從結(jié)構(gòu)只能保證數(shù)據(jù)有備份沮协,但是如果主掛掉了,怎么辦卓嫂,整個(gè)服務(wù)就不可用了慷暂,這顯然是個(gè)大問(wèn)題。當(dāng)然redis也幫我們考慮到了這一點(diǎn)晨雳。解決方案就是哨兵行瑞。他可以作為一個(gè)第三方,監(jiān)控著我們主節(jié)點(diǎn)的狀態(tài)餐禁,當(dāng)發(fā)現(xiàn)主掛掉后血久,就會(huì)從這個(gè)主的從服務(wù)器中進(jìn)行選舉,推選出一個(gè)新主帮非,同時(shí)slave也切換成這個(gè)新主的slave,如果原來(lái)的主重啟成功了也不會(huì)再次成為主了氧吐,而是作為slave掛到新主上。現(xiàn)在我們?cè)僦鸩竭M(jìn)行驗(yàn)證末盔。因?yàn)樯婕暗竭x舉所以一個(gè)slave肯定是不夠的筑舅,所以最少是兩個(gè),上面我們的6380已經(jīng)是一個(gè)從了陨舱,所以我們?cè)傩陆ㄒ粋€(gè)6381的從服務(wù)器翠拣。配置如下
bind 127.0.0.1
port 6381
pidfile "/Users/olifer/middle/redis/slave/redis_6381.pid"
dir "/Users/olifer/middle/redis/slave2"
slaveof 127.0.0.1 6379
啟動(dòng)redis-server redis-conf后出現(xiàn)下面的頁(yè)面,說(shuō)明配置成功
1229:S 02 Dec 19:57:08.243 # Server started, Redis version 3.2.11
1229:S 02 Dec 19:57:08.243 * DB loaded from disk: 0.000 seconds
1229:S 02 Dec 19:57:08.243 * The server is now ready to accept connections on port 6381
1229:S 02 Dec 19:57:08.243 * Connecting to MASTER 127.0.0.1:6379
下面我們?cè)倥渲蒙诒蚊ぃ鋵?shí)也是特別的簡(jiǎn)單误墓,我們可以從redis的源文件中找到sentinel.conf配置文件,他就是哨兵的配置
port 26379
sentinel monitor mymaster 127.0.0.1 6379 1
sentinel down-after-milliseconds mymaster 5000
sentinel parallel-syncs mymaster 2
port不用多說(shuō)益缎,就是一個(gè)端口號(hào)优烧。我們說(shuō)一下這個(gè)配置,sentinel monitor mymaster 127.0.0.1 6379 1链峭,我們給監(jiān)控的主節(jié)點(diǎn)起了個(gè)名字叫做mymaster,他的位置是127.0.0.1,端口是6379又沾,主掛掉后我們要通過(guò)選舉獲得最新的主弊仪,所以1代表了法定的人數(shù),也就是有1臺(tái)服務(wù)器同意這個(gè)提案就可以杖刷。這個(gè)配置sentinel down-after-milliseconds mymaster 5000励饵,表示master或slave 5s(默認(rèn)30秒)不能使用后標(biāo)記為s_down狀態(tài)。sentinel parallel-syncs mymaster 2,指定了在執(zhí)行故障轉(zhuǎn)移時(shí)滑燃, 最多可以有多少個(gè)從服務(wù)器同時(shí)對(duì)新的主服務(wù)器進(jìn)行同步役听,配置完成后,開(kāi)始啟動(dòng)
redis-sentinel sentinel.conf
1385:X 02 Dec 20:12:44.725 * Increased maximum number of open files to 10032 (it was originally set to 7168).
_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 3.2.11 (00000000/0) 64 bit
.-`` .-```. ```\/ _.,_ ''-._
( ' , .-` | `, ) Running in sentinel mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 26379
| `-._ `._ / _.-' | PID: 1385
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | http://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
1385:X 02 Dec 20:12:44.726 # Sentinel ID is 104e563c9931120931c3594973cab424509c2646
1385:X 02 Dec 20:12:44.726 # +monitor master mymaster 127.0.0.1 6379 quorum 1
1385:X 02 Dec 20:12:44.727 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
1385:X 02 Dec 20:12:44.728 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
從這個(gè)日志中我們可以看出,記錄了master的信息(127.0.0.1 6379)典予,也記錄了slave的信息(127.0.0.1 6380,127.0.0.1 6381).我們可以進(jìn)入查看一下
redis-cli -p 26379
就可以查看一下master,slave包括哨兵的信息
sentinel master mymaster //查看master的狀態(tài)
sentinel slaves mymaster //查看salves的狀態(tài)
sentinel sentinels mymaster //查看哨兵的狀態(tài)
info sentinel //查看哨兵信息
我們的環(huán)境配置好了甜滨,就可以驗(yàn)證一些問(wèn)題了。第一個(gè)問(wèn)題當(dāng)主掛掉能否自動(dòng)切換瘤袖,從slave中挑選一臺(tái)作為主衣摩。下面我們就把master shutdown.我們可以從哨兵的日志中發(fā)現(xiàn)一段這樣的日志
1385:X 02 Dec 20:26:49.199 # +sdown master mymaster 127.0.0.1 6379
1385:X 02 Dec 20:26:49.199 # +odown master mymaster 127.0.0.1 6379 #quorum 1/1
1385:X 02 Dec 20:26:49.199 # +new-epoch 1
1385:X 02 Dec 20:26:49.199 # +try-failover master mymaster 127.0.0.1 6379
1385:X 02 Dec 20:26:49.208 # +vote-for-leader 104e563c9931120931c3594973cab424509c2646 1
1385:X 02 Dec 20:26:49.208 # +elected-leader master mymaster 127.0.0.1 6379
1385:X 02 Dec 20:26:49.208 # +failover-state-select-slave master mymaster 127.0.0.1 6379
1385:X 02 Dec 20:26:49.274 # +selected-slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
1385:X 02 Dec 20:26:49.274 * +failover-state-send-slaveof-noone slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
1385:X 02 Dec 20:26:49.379 * +failover-state-wait-promotion slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
1385:X 02 Dec 20:26:50.309 # +promoted-slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
1385:X 02 Dec 20:26:50.309 # +failover-state-reconf-slaves master mymaster 127.0.0.1 6379
1385:X 02 Dec 20:26:50.391 * +slave-reconf-sent slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
1385:X 02 Dec 20:26:51.332 * +slave-reconf-inprog slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
1385:X 02 Dec 20:26:52.392 * +slave-reconf-done slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
1385:X 02 Dec 20:26:52.447 # +failover-end master mymaster 127.0.0.1 6379
1385:X 02 Dec 20:26:52.447 # +switch-master mymaster 127.0.0.1 6379 127.0.0.1 6380
1385:X 02 Dec 20:26:52.447 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
1385:X 02 Dec 20:26:52.447 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
1385:X 02 Dec 20:26:57.489 # +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
每個(gè)sentinel會(huì)向其它sentinal、master捂敌、slave定時(shí)發(fā)送消息艾扮,以確認(rèn)對(duì)方是否“活”著,如果發(fā)現(xiàn)對(duì)方在指定時(shí)間(可配置)內(nèi)未回應(yīng)占婉,則暫時(shí)認(rèn)為對(duì)方已掛(所謂的“主觀認(rèn)為宕機(jī)” Subjective Down泡嘴,簡(jiǎn)稱SDOWN)。若“哨兵群”中的多數(shù)sentinel逆济,都報(bào)告某一master沒(méi)響應(yīng)酌予,系統(tǒng)才認(rèn)為該master"徹底死亡"(即:客觀上的真正down機(jī),Objective Down纹腌,簡(jiǎn)稱ODOWN)霎终,通過(guò)一定的vote算法,從剩下的slave節(jié)點(diǎn)中升薯,選一臺(tái)提升為master莱褒,然后自動(dòng)修改相關(guān)配置。到最后通過(guò)選舉決定了6380作為新的主涎劈,同時(shí)將6379(已經(jīng)掛掉)與6381(存活)作為 6380 的slave广凸。這時(shí)候我們看一下各個(gè)節(jié)點(diǎn)的配置文件。首先看一下6380蛛枚,原來(lái)配置文件中的slaveof 127.0.0.1 6379 已經(jīng)刪掉了谅海,說(shuō)明他已經(jīng)不是從節(jié)點(diǎn)了,那么他就變成主節(jié)點(diǎn)了蹦浦。在看一下6381 ,他的配置已經(jīng)從原來(lái)的slaveof 127.0.0.1 6379 變成了 slaveof 127.0.0.1 6380扭吁。看一下哨兵的配置文件盲镶,最下面多了幾行
# Generated by CONFIG REWRITE
sentinel config-epoch mymaster 1
sentinel leader-epoch mymaster 1
sentinel known-slave mymaster 127.0.0.1 6379
sentinel known-slave mymaster 127.0.0.1 6381
sentinel current-epoch 1
說(shuō)明哨兵也已經(jīng)做好了切換侥袜。6379這時(shí)候在哨兵的眼里就是一個(gè)slave了,所以他重啟后溉贿,不可能變成主了枫吧,只能是從了。我們現(xiàn)在啟動(dòng)6379 ,在哨兵的日志中增加了下面兩行
1385:X 02 Dec 20:40:09.929 # -sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
1385:X 02 Dec 20:40:19.872 * +convert-to-slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
在6379的redis-conf文件的最后面宇色,增加了兩行
# Generated by CONFIG REWRITE
slaveof 127.0.0.1 6380
所以總的過(guò)程就是當(dāng)哨兵發(fā)現(xiàn)主掛掉后九杂,會(huì)通過(guò)選舉選出新主颁湖,slave的關(guān)系進(jìn)行切換。整個(gè)過(guò)程順滑例隆、完整甥捺。不得不說(shuō)做的很漂亮啊。