redis 主從復(fù)制與哨兵模式

上一篇文章我們簡單介紹了redis api 的使用方式,本節(jié)的內(nèi)容,我們講一下他是如何保證高可用的。
測試版本是redis-3.2.11,從官網(wǎng)拉去到源碼后,進(jìn)行編譯make,就會在src目錄下看到很多可執(zhí)行文件,例如redis-server,redis-cli,redis-sentinel等大家耳熟能詳?shù)摹?/p>

首先我們解釋一下主從的區(qū)別:主對于數(shù)據(jù)可讀可寫。從默認(rèn)是只讀不寫的。當(dāng)從連接上主時,主會將數(shù)據(jù)同步到從上。詳細(xì)的內(nèi)容我們可以參考一下Redis主從同步原理-SYNC這篇文章講的還是很詳細(xì)的。

哨兵:當(dāng)主掛掉,哨兵可以通過選舉從從服務(wù)器中選擇一臺作為主,提供高可用的方案。注意當(dāng)原來的主恢復(fù)時,也將成為現(xiàn)在主的從服務(wù)器。

概念解釋完了,我們來搭建環(huán)境。首先我們搭建的是主從。從最基本的一主一從開始。

主的配置相較于默認(rè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"

配置好了我們啟動服務(wù)redis-server redis.conf , 如果看到下面的文字,說明啟動成功

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

從的配置也相對較為簡單,端口改一下6380,最為主要的是配置slaveof,指明他的主是誰

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

配置好了我們啟動服務(wù)redis-server redis.conf , 如果看到下面的文字,說明啟動成功

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

通過slave的日志我們可以看出,啟動成功,暴露端口為6380,并且連接上了自己的主6379,并且開始了同步數(shù)據(jù)。

這時候我們可以看一下主的日志,同樣也能得到類似的信息,從主的日志可以看出,從確實連接上了主,并且愛是同步數(shù)據(jù)到從服務(wù)器,這個數(shù)據(jù)同步的過程我們會在下一篇文章中講述。

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

目前為止我們一個redis的主從就這么搭建好了,是不是超級簡單,搭建好了,我們就需要驗證功能了。我們使用redis-cli連接到主上,也就是6379。當(dāng)然你也可以不用指定-p,因為默認(rèn)的就是6379,這樣就可以進(jìn)入到redis shell的操作界面。我們簡單的set一個值

redis-cli -p 6379
127.0.0.1:6379> set name olifer
OK

這時候我們驗證一下從服務(wù)器的數(shù)據(jù)有沒有同步過來。

redis-cli -p 6380
127.0.0.1:6380> get name
"olifer"

和我們預(yù)想的是一致的,我們從從的服務(wù)器上可以獲取到主的數(shù)據(jù),更為確切的說,是主從數(shù)據(jù)進(jìn)行了準(zhǔn)實時的同步,所以可以從從服務(wù)器上獲取到數(shù)據(jù)。

我們可以往從服務(wù)器上設(shè)置值嗎?實踐是檢驗真理的唯一的方式,試一下

127.0.0.1:6380> set age 123
(error) READONLY You can't write against a read only slave.

發(fā)現(xiàn)報錯了,slave默認(rèn)情況下是不能寫數(shù)據(jù),只能讀取數(shù)據(jù)。當(dāng)然這個也是可以設(shè)置的,在從的配置文件中有這個一個配置

slave-read-only yes

從名字我們就看出來他是只讀的,如果我們想slave也可以寫,我們可以修改此配置為no,之后我們重啟一下,看結(jié)果就可以了。

127.0.0.1:6380> set age 123
OK

所以一些有用的配置大家還是屬性一下吧。

現(xiàn)在大家思考一個問題,主從結(jié)構(gòu)只能保證數(shù)據(jù)有備份,但是如果主掛掉了,怎么辦,整個服務(wù)就不可用了,這顯然是個大問題。當(dāng)然redis也幫我們考慮到了這一點。解決方案就是哨兵。他可以作為一個第三方,監(jiān)控著我們主節(jié)點的狀態(tài),當(dāng)發(fā)現(xiàn)主掛掉后,就會從這個主的從服務(wù)器中進(jìn)行選舉,推選出一個新主,同時slave也切換成這個新主的slave,如果原來的主重啟成功了也不會再次成為主了,而是作為slave掛到新主上?,F(xiàn)在我們再逐步進(jìn)行驗證。因為涉及到選舉所以一個slave肯定是不夠的,所以最少是兩個,上面我們的6380已經(jīng)是一個從了,所以我們再新建一個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

啟動redis-server redis-conf后出現(xiàn)下面的頁面,說明配置成功

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

下面我們再配置哨兵,其實也是特別的簡單,我們可以從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不用多說,就是一個端口號。我們說一下這個配置,sentinel monitor mymaster 127.0.0.1 6379 1,我們給監(jiān)控的主節(jié)點起了個名字叫做mymaster,他的位置是127.0.0.1,端口是6379,主掛掉后我們要通過選舉獲得最新的主,所以1代表了法定的人數(shù),也就是有1臺服務(wù)器同意這個提案就可以。這個配置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)移時, 最多可以有多少個從服務(wù)器同時對新的主服務(wù)器進(jìn)行同步,配置完成后,開始啟動

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

從這個日志中我們可以看出,記錄了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)境配置好了,就可以驗證一些問題了。第一個問題當(dāng)主掛掉能否自動切換,從slave中挑選一臺作為主。下面我們就把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

每個sentinel會向其它sentinal、master、slave定時發(fā)送消息,以確認(rèn)對方是否“活”著,如果發(fā)現(xiàn)對方在指定時間(可配置)內(nèi)未回應(yīng),則暫時認(rèn)為對方已掛(所謂的“主觀認(rèn)為宕機(jī)” Subjective Down,簡稱SDOWN)。若“哨兵群”中的多數(shù)sentinel,都報告某一master沒響應(yīng),系統(tǒng)才認(rèn)為該master"徹底死亡"(即:客觀上的真正down機(jī),Objective Down,簡稱ODOWN),通過一定的vote算法,從剩下的slave節(jié)點中,選一臺提升為master,然后自動修改相關(guān)配置。到最后通過選舉決定了6380作為新的主,同時將6379(已經(jīng)掛掉)與6381(存活)作為 6380 的slave。這時候我們看一下各個節(jié)點的配置文件。首先看一下6380,原來配置文件中的slaveof 127.0.0.1 6379 已經(jīng)刪掉了,說明他已經(jīng)不是從節(jié)點了,那么他就變成主節(jié)點了。在看一下6381 ,他的配置已經(jīng)從原來的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

說明哨兵也已經(jīng)做好了切換。6379這時候在哨兵的眼里就是一個slave了,所以他重啟后,不可能變成主了,只能是從了。我們現(xiàn)在啟動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

所以總的過程就是當(dāng)哨兵發(fā)現(xiàn)主掛掉后,會通過選舉選出新主,slave的關(guān)系進(jìn)行切換。整個過程順滑、完整。不得不說做的很漂亮啊。

參考文章:
redis可用性提升(哨兵sentinel)配置示例
redis哨兵配置主從

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • "只要站在風(fēng)口,豬也能飛上天",這幾年網(wǎng)店,團(tuán)購,APP,智能硬件一波接著一波,今年人工智能又要"火".弄得我都不...
    xieyan0811閱讀 344評論 0 1
  • Crop 裁剪圖片Repo(備用): https://github.com/jeduan/cordova-plug...
    待花謝花開閱讀 801評論 0 1
  • 寫這篇文章的時候,我剛與一玻璃心的人心塞至此,但現(xiàn)在我只想平心氣和的寫完這篇文章,希望我以后不要輕易忘記對自己的告...
    葉子吶閱讀 3,781評論 0 0

友情鏈接更多精彩內(nèi)容