redis 系列(三)- redis主從復(fù)制和哨兵模式

普通主從架構(gòu)(讀寫分離)

問題

持久化解決了單機(jī)redis的數(shù)據(jù)保存問題淮捆,但是redis還是存在以下兩個問題:

  1. 假如某天這臺redis服務(wù)器掛了,redis服務(wù)將徹底喪失
  2. redis的讀和寫都集中到一臺機(jī)上黑界,如果請求量比較大時(shí)救斑,將可能被擊潰
解決

為了解決上述兩個問題心褐,redis提供了主從架構(gòu),在主從架構(gòu)中誊役,主服務(wù)器負(fù)責(zé)寫服務(wù)获列,多臺從服務(wù)器負(fù)責(zé)讀服務(wù),緩解了單個redis服務(wù)器的壓力蛔垢;主服務(wù)器將所有數(shù)據(jù)源源不斷的同步到從服務(wù)器上击孩,一旦主服務(wù)器掛了,還有從服務(wù)器可以提供服務(wù)鹏漆,redis服務(wù)將不會間斷巩梢。

特點(diǎn)
  1. 一臺主服務(wù)器可以連接多臺從服務(wù)器
  2. 從服務(wù)器也可以連接其他redis服務(wù)器创泄,作為其他redis服務(wù)器的主服務(wù)器,從而形成一條鏈
  3. 主從同步是異步的括蝠,從服務(wù)器不會阻塞鞠抑,但是在數(shù)據(jù)寫到從服務(wù)器內(nèi)存的這段期間,從服務(wù)器對外提供的還是舊的數(shù)據(jù)
類型
  1. 全量同步 指主服務(wù)器每次與從服務(wù)器同步都是同步全部數(shù)據(jù)忌警。主服務(wù)器持久化數(shù)據(jù)為一個rdb文件搁拙,在此期間用緩存區(qū)把所有對主服務(wù)器的寫操作命令存儲起來了,然后再rdb傳給從服務(wù)器慨蓝,再把儲存起來的命令也傳過去感混;從服務(wù)器從接收到的rdb文件加載數(shù)據(jù),然后再加載傳過來的命令礼烈。
  2. 部分同步 指主服務(wù)器每次與從服務(wù)器同步都是只同步增量數(shù)據(jù)弧满。

原理

  1. 從服務(wù)器收到客戶端的saveof命令,檢查是否存儲了主服務(wù)器的運(yùn)行id和復(fù)制偏移量此熬。
  2. 如果沒綁存儲庭呜,從服務(wù)器發(fā)送 psync 1命令和主服務(wù)器進(jìn)行一次全量復(fù)制,并且保存主服務(wù)器發(fā)過來的運(yùn)行id 和 復(fù)制偏移量
  3. 如果有存儲了犀忱,從服務(wù)器發(fā)送運(yùn)行id和復(fù)制偏移量募谎,主服務(wù)器比較運(yùn)行id是否一致,復(fù)制偏移量是否正常阴汇,如果不一致或者不正常数冬,進(jìn)行全量同步
  4. 如果運(yùn)行id和復(fù)制偏移量正常,那么二者進(jìn)行增量同步搀庶,同步根據(jù)傳過來復(fù)制偏移量拐纱,到復(fù)制緩存區(qū)找到對應(yīng)的字節(jié),并且把該字節(jié)對應(yīng)的之后的命令都同步過去
操作
  • slaveof master-ip master-port 在從服務(wù)器的redis.conf中配置主服務(wù)器的host,port
  • slave-read-only yes 從服務(wù)器默認(rèn)只讀哥倔,這里可改成no為可寫(可選)
  • auth 從服務(wù)器配置主服務(wù)器的密碼(可選)
  • requirepass 主服務(wù)器配置密碼(可選)

從服務(wù)器配置好slaveof master-ip master-port 后重啟秸架,就可以與主服務(wù)器進(jìn)行同步了。

# 主服務(wù)器信息
172.17.0.3:6379> info replication
role:master
connected_slaves:2
# 兩個從服務(wù)器復(fù)制偏移量為4908
slave0:ip=172.17.0.4,port=6379,state=online,offset=4908,lag=1
slave1:ip=172.17.0.5,port=6379,state=online,offset=4908,lag=1
# 主服務(wù)器的復(fù)制偏移量也為4908
master_repl_offset:4908
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:4907

哨兵模式

作用
  • 不斷的檢查主從架構(gòu)中的redis服務(wù)中正常運(yùn)行咆蒿。
  • 如果出現(xiàn)問題會發(fā)信息提示你东抹。
  • 如果主服務(wù)器掛了的話,會從從服務(wù)器中重新選舉一臺作為主服務(wù)器沃测。
原理
  • 哨兵系統(tǒng)的分類
    哨兵系統(tǒng)可以分為單哨兵和多哨兵缭黔;單哨兵是指只有一個哨兵進(jìn)程,多哨兵是指有多個哨兵進(jìn)程蒂破;單哨兵掛了的話试浙,哨兵系統(tǒng)也就掛了,多哨兵只有一個哨兵掛了不影響哨兵系統(tǒng)繼續(xù)提供服務(wù)寞蚌。

  • 大概原理
    哨兵也是一個Linux的進(jìn)程田巴;各個哨兵分布在不同的Linux服務(wù)器或者同一個Linux服務(wù)器上(一個風(fēng)險(xiǎn)比較大)钠糊,它們不停的監(jiān)控redis的主服務(wù)器和從服務(wù)器與其它的哨兵進(jìn)程,一旦察覺redis主服務(wù)掛了壹哺,就會從從服務(wù)器中選出一個作為新的主服務(wù)器提供服務(wù)抄伍。

  • 哨兵怎么知道監(jiān)控其它哨兵和redis服務(wù)?
    哨兵每秒鐘會向其它哨兵或者redis服務(wù)器發(fā)送ping命令管宵,根據(jù)是否有返回來判斷服務(wù)是否已經(jīng)下線截珍。

  • 我們只是在哨兵的配置文件里配置了主服務(wù)器信息,但是它怎么知道從服務(wù)器信息箩朴?
    哨兵每十秒鐘會向redis主服務(wù)器或者從服務(wù)器執(zhí)行info replication的命令朗儒,來確認(rèn)它們的主從關(guān)系厢绝。

  • 我們沒有配置其他哨兵的地址都伪,哨兵怎么知道其他哨兵地址翠勉?
    哨兵每隔兩秒就會向redis主節(jié)點(diǎn)的sentinel:hello頻道發(fā)布哨兵對于主節(jié)點(diǎn)的判斷以及當(dāng)前哨兵的信息,其它哨兵也會也會如此埠居,并且從中獲取所有的哨兵信息查牌。

  • 確認(rèn)一臺redis服務(wù)器下線經(jīng)歷了什么流程?
    哨兵不斷的PING redis服務(wù)器滥壕,當(dāng)發(fā)現(xiàn)服務(wù)器超過配置的down-after-milliseconds的時(shí)間都沒有響應(yīng)纸颜,就會認(rèn)為這臺主觀下線;這時(shí)候哨兵會向其他哨兵發(fā)送is-master-down-by-addr命令詢問是否可以標(biāo)記為客觀下線绎橘,當(dāng)認(rèn)為這臺redis服務(wù)器主觀下線的哨兵超過我們配置的quorum(一般設(shè)為哨兵數(shù)量的一半加1)的值的時(shí)候胁孙,我們就可以認(rèn)為這臺redis服務(wù)器客觀下線。為什么還要去詢問其他哨兵呢称鳞?這是因?yàn)樯诒蛂edis服務(wù)器之間沒有ping成功也可以能網(wǎng)絡(luò)之間的問題涮较。

  • 為什么要對哨兵進(jìn)行領(lǐng)導(dǎo)者選舉?
    當(dāng)確定redis服務(wù)器確實(shí)掛了以后胡岔,哨兵要進(jìn)行故障轉(zhuǎn)移法希,并且只能有一個哨兵去完成該操作枷餐,所以這時(shí)候就要選舉出一名哨兵來當(dāng)此重任靶瘸。那怎么選舉呢?

  1. 哨兵向其它哨兵發(fā)送is-master-down-by-addr除了確認(rèn)是否機(jī)器是否可以下線以外毛肋,會有發(fā)起選舉的作用
  2. 其它哨兵收到命令以后怨咪,如果如果沒有答應(yīng)其它哨兵的選舉請求就會答應(yīng)該哨兵的請求
  3. 當(dāng)同意(包括自己)的哨兵個數(shù)達(dá)到quorum,該哨兵就會成為領(lǐng)導(dǎo)者
  • 怎么完成故障轉(zhuǎn)移润匙?
    當(dāng)確定原來的redis主服務(wù)器已經(jīng)客觀下線以后诗眨,就會從從服務(wù)器中選出一臺作為新的主服務(wù)器,選擇順序如下:
  1. 看配置的slave-priority孕讳,如果從服務(wù)器不相等匠楚,返回最高的那臺巍膘,如果相同看下一步
  2. 看offset,即復(fù)制偏移量芋簿,如果復(fù)制偏移量不同峡懈,返回最高那臺,如果相同看下一步
  3. 看runid与斤,程序id肪康,runid越低可以看做是越早開啟,返回越低那臺

確定完是哪臺從服務(wù)器作為新的主服務(wù)器以后撩穿,會修改新的從服務(wù)器的slaveof與各個哨兵的監(jiān)控的主服務(wù)器的地址和ip磷支。

舉個栗子

開啟三個redis服務(wù),一主兩從食寡;開啟三個哨兵雾狈;把主服務(wù)器關(guān)閉掉,查看從服務(wù)器是否會產(chǎn)生新的主服務(wù)器冻河。

redis配置
# 主服務(wù)器 redis-6379.conf
port 6379 
daemonize yes
protected-mode no
logfile "6379.log"
dbfilename "dump-6379.rdb"

# 從服務(wù)器 redis-6380.conf
port 6380 
daemonize yes
protected-mode no
logfile "6380.log"
dbfilename "dump-6380.rdb"
slaveof 139.199.168.61 6379

# 從服務(wù)器 redis-6381.conf
port 6381 
daemonize yes
protected-mode no
logfile "6381.log"
dbfilename "dump-6381.rdb"
slaveof 139.199.168.61 6379

redis-server redis-6379.conf 啟動各個redis服務(wù)箍邮。

哨兵配置
#sentinel-26379.conf
port 26379
daemonize yes
protected-mode no
logfile "26379.log"
#監(jiān)控的redis主服務(wù)器,最后面的2就是上面提到的quorum,當(dāng)哨兵響應(yīng)的個數(shù)超過這個數(shù)叨叙,redis服務(wù)器才會被認(rèn)為是客觀下線
sentinel monitor mymaster 139.199.168.61 6379 2
#當(dāng)超過這個值redis服務(wù)器對哨兵的ping不做出響應(yīng)會被哨兵認(rèn)為是主觀下線
sentinel down-after-milliseconds mymaster 10000

#sentinel-26380.conf
port 26380
daemonize yes
protected-mode no
logfile "26380.log"
sentinel monitor mymaster 139.199.168.61 6379 2
sentinel down-after-milliseconds mymaster 10000

#sentinel-26381.conf
port 26381
daemonize yes
protected-mode no
logfile "26381.log"
sentinel monitor mymaster 139.199.168.61 6379 2
sentinel down-after-milliseconds mymaster 10000

redis-sentinel sentinel-26379.conf 啟動各個哨兵服務(wù)锭弊。

哨兵啟動后我們可以查看sentinel-26379.conf:

port 26379
daemonize yes
protected-mode no
logfile "26379.log"
sentinel myid f65e6f01127c838e023f48b73c0f9642548a176d
sentinel monitor mymaster 139.199.168.61 6379 2
# Generated by CONFIG REWRITE
dir "/usr/local/redis-3.2.6"
sentinel down-after-milliseconds mymaster 10000
sentinel config-epoch mymaster 0
sentinel leader-epoch mymaster 0
sentinel known-slave mymaster 139.199.168.61 6381
sentinel known-slave mymaster 139.199.168.61 6380
sentinel known-sentinel mymaster 10.104.90.159 26381 a8ca7a98c5b462c5c341650386be589cf31a5761
sentinel known-sentinel mymaster 10.104.90.159 26380 eb637934a6e00a26c36fef681cb1e194127b7d2c
sentinel current-epoch 0

會發(fā)現(xiàn)哨兵已經(jīng)把redis的從服務(wù)器和其他哨兵加進(jìn)來了,我們關(guān)閉主服務(wù)器kill redis主服務(wù)器的進(jìn)程擂错,再查看sentinel-26379.conf

port 26379
daemonize yes
protected-mode no
logfile "26379.log"
sentinel myid f65e6f01127c838e023f48b73c0f9642548a176d
sentinel monitor mymaster 139.199.168.61 6381 2
# Generated by CONFIG REWRITE
dir "/usr/local/redis-3.2.6"
sentinel down-after-milliseconds mymaster 10000
sentinel config-epoch mymaster 1
sentinel leader-epoch mymaster 1
sentinel known-slave mymaster 139.199.168.61 6379
sentinel known-slave mymaster 139.199.168.61 6380
sentinel known-sentinel mymaster 10.104.90.159 26381 a8ca7a98c5b462c5c341650386be589cf31a5761
sentinel known-sentinel mymaster 10.104.90.159 26380 eb637934a6e00a26c36fef681cb1e194127b7d2c
sentinel current-epoch 1

我們可以看到監(jiān)控的主服務(wù)器已經(jīng)切換成 6381而不是之前的6379了味滞。

Java使用
  • Java使用redis的一般做法:
  Jedis jedis = new Jedis("139.199.168.61", 6379);
  System.out.println(jedis.get("hello"));

這種做法最大的弊端在于萬一139.199.168.61:6379 這個redis掛了,這個Java應(yīng)用就廢了钮呀。

  • 如果我們現(xiàn)在知道了哨兵模式剑鞍,我們可以改寫成以下的做法:
        //聲明一個set 存放哨兵集群的地址和端口
        Set<String> sentinels = new HashSet<String>();
        sentinels.add("139.199.168.61:26379");
        sentinels.add("139.199.168.61:26380");
        sentinels.add("139.199.168.61:26381");
        JedisSentinelPool sentinelPool = new JedisSentinelPool("mymaster", sentinels);
        // 使用sentinelPool獲取jedis對象
        Jedis master = sentinelPool.getResource();
        System.out.println(master.get("hello"));
        master.close();
        sentinelPool.destroy();

這樣子,當(dāng)主服務(wù)器掛掉以后爽醋,哨兵集群會返回給程序新的主服務(wù)器地址蚁署,保證服務(wù)不會掛掉。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蚂四,一起剝皮案震驚了整個濱河市光戈,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌遂赠,老刑警劉巖久妆,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異跷睦,居然都是意外死亡筷弦,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進(jìn)店門抑诸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來烂琴,“玉大人爹殊,你說我怎么就攤上這事〖楸粒” “怎么了边灭?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長健盒。 經(jīng)常有香客問我绒瘦,道長,這世上最難降的妖魔是什么扣癣? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任惰帽,我火速辦了婚禮,結(jié)果婚禮上父虑,老公的妹妹穿的比我還像新娘该酗。我一直安慰自己,他們只是感情好士嚎,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布呜魄。 她就那樣靜靜地躺著,像睡著了一般莱衩。 火紅的嫁衣襯著肌膚如雪爵嗅。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天笨蚁,我揣著相機(jī)與錄音睹晒,去河邊找鬼。 笑死括细,一個胖子當(dāng)著我的面吹牛伪很,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播奋单,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼锉试,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了览濒?” 一聲冷哼從身側(cè)響起呆盖,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎匾七,沒想到半個月后絮短,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體江兢,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡昨忆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了杉允。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片邑贴。...
    茶點(diǎn)故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡席里,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出拢驾,到底是詐尸還是另有隱情奖磁,我是刑警寧澤,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布繁疤,位于F島的核電站咖为,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏稠腊。R本人自食惡果不足惜躁染,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望架忌。 院中可真熱鬧吞彤,春花似錦、人聲如沸叹放。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽井仰。三九已至埋嵌,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間俱恶,已是汗流浹背莉恼。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留速那,地道東北人俐银。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像端仰,于是被迫代替她去往敵國和親捶惜。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評論 2 353

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