Redis主從復(fù)制、哨兵、Cluster三種模式詳細(xì)介紹

這篇文章主要講解了“redis主從復(fù)制、哨兵、Cluster三種模式詳細(xì)介紹”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“Redis主從復(fù)制、哨兵、Cluster三種模式詳細(xì)介紹”吧!

專注于為中小企業(yè)提供成都做網(wǎng)站、成都網(wǎng)站建設(shè)、成都外貿(mào)網(wǎng)站建設(shè)服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)余杭免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動(dòng)了成百上千企業(yè)的穩(wěn)健成長(zhǎng),幫助中小企業(yè)通過(guò)網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。

 
 

概述

Redis作為緩存的高效中間件,在我們?nèi)粘5拈_發(fā)中被頻繁的使用,今天就來(lái)說(shuō)一說(shuō)Redis的四種模式,分別是「單機(jī)版、主從復(fù)制、哨兵、以及集群模式」。

可能,在一般公司的程序員使用單機(jī)版基本都能解決問(wèn)題,在Redis的官網(wǎng)給出的數(shù)據(jù)是10W QPS,這對(duì)于應(yīng)付一般的公司綽綽有余了,再不行就來(lái)個(gè)主從模式,實(shí)現(xiàn)讀寫分離,性能又大大提高。

但是,我們作為有抱負(fù)的程序員,僅限于單機(jī)版和主從模式的crud是不行的,至少也要了解「哨兵」「集群模式」的原理,這樣面試的時(shí)候才能和面試官扯皮啊。

之前對(duì)于Redis方面也是寫了比較多的文章,如:「Redis的基本數(shù)據(jù)類型和底層的實(shí)現(xiàn)原理、事務(wù)、持久化、分布式鎖、訂閱預(yù)發(fā)布」等,可以說(shuō)是比較全面的教程了,這篇講完基本就全了,我會(huì)把文章系統(tǒng)的整理成pdf,分享給大家。

先來(lái)個(gè)整理的Redis大綱,可能還有不完整的地方,若是有不完整的,可以在留言區(qū)補(bǔ)充,我后續(xù)會(huì)加進(jìn)去。

Redis主從復(fù)制、哨兵、Cluster三種模式詳細(xì)介紹  
 

單機(jī)

單機(jī)版的Redis就比較簡(jiǎn)單了,基本90%的程序員都是用過(guò),官網(wǎng)推薦操作Redis的第三方依賴庫(kù)是Jedis,在SpringBoot項(xiàng)目中,引入下面依賴就可以直接使用了:

<dependency>
   <groupId>redis.clients</groupId>
   <artifactId>jedis</artifactId>
   <version>${jedis.version}</version>
</dependency>
   

優(yōu)點(diǎn)

單機(jī)版的Redis也有很多優(yōu)點(diǎn),比如實(shí)現(xiàn)實(shí)現(xiàn)簡(jiǎn)單、維護(hù)簡(jiǎn)單、部署簡(jiǎn)單、維護(hù)成本非常低,不需要其它額外的開支。

 

缺點(diǎn)

但是,因?yàn)槭菃螜C(jī)版的Redis所以也存在很多的問(wèn)題,比如最明顯的單點(diǎn)故障問(wèn)題,一個(gè)Redis掛了,所有的請(qǐng)求就會(huì)直接打在了DB上。

并且一個(gè)Redis抗并發(fā)數(shù)量也是有限的,同時(shí)要兼顧讀寫兩種請(qǐng)求,只要訪問(wèn)量一上來(lái),Redis就受不了了,另一方面單機(jī)版的Redis數(shù)據(jù)量存儲(chǔ)也是有限的,數(shù)據(jù)量一大,再重啟Redis的時(shí)候,就會(huì)非常的慢,所以局限性也是比較大的。

 

實(shí)操搭建

單機(jī)版的搭建教程,在網(wǎng)上有非常多的全面的教程,基本就是傻瓜式操作,特別是在本地搭建的話,基本使用yum快捷方便,幾句命令就搞定了,這里推薦一個(gè)搭建教程:https://www.cnblogs.com/ zuidongfeng/p/8032505.html。

上面這個(gè)教程講的非常的詳細(xì),環(huán)境的搭建本來(lái)是運(yùn)維的工作,但是作為程序員嘗試自己去搭建環(huán)境還是有必要的,而且搭建環(huán)境這種東西,基本就是一勞永逸,搭建一次,可能下次換電腦或者重裝虛擬機(jī)才會(huì)再次搭建。

這里也放出redis常用的redis.conf的配置項(xiàng),并且附帶注釋,看我是不是很暖男:

daemonize yes  // 設(shè)置后臺(tái)啟動(dòng),一般設(shè)置yes
pidfile /var/run/redis.pid // edis以守護(hù)進(jìn)程方式運(yùn)行時(shí),redis默認(rèn)會(huì)把pid寫入/var/run/redis.pid文件
port 6379 // 默認(rèn)端口為6379
bind 127.0.0.1 //主機(jī)地址,設(shè)置0.0.0.0表示都可以訪問(wèn)。127.0.0.1表示只允許本機(jī)訪問(wèn)
timeout 900  // 客戶端閑置多長(zhǎng)時(shí)間后關(guān)閉連接,如果指定為0,表示關(guān)閉該功能
logfile stdout // 日志記錄方式,默認(rèn)為標(biāo)準(zhǔn)輸出
logfile "./redis7001.log"  # 指明日志文件名
databases 16 // 設(shè)置數(shù)據(jù)庫(kù)的數(shù)量,默認(rèn)數(shù)據(jù)庫(kù)為0
save  //有多少次更新操作,就將數(shù)據(jù)同步到數(shù)據(jù)文件
 Redis默認(rèn)配置文件中提供了三個(gè)條件:
 save 900 1 //900秒(15分鐘)內(nèi)有1個(gè)更改
 save 300 10 //300秒(5分鐘)內(nèi)有10個(gè)更改
 save 60 10000  // 60秒內(nèi)有10000個(gè)更改
rdbcompression yes // 指定存儲(chǔ)至本地?cái)?shù)據(jù)庫(kù)時(shí)是否壓縮數(shù)據(jù)
dbfilename dump.rdb //指定本地?cái)?shù)據(jù)庫(kù)文件名
dir ./    //指定本地?cái)?shù)據(jù)庫(kù)存放目錄
slaveof  // 主從同步設(shè)置,設(shè)置主數(shù)據(jù)庫(kù)的ip和端口
# 如果非零,則設(shè)置SO_KEEPALIVE選項(xiàng)來(lái)向空閑連接的客戶端發(fā)送ACK
tcp-keepalive 60
# 默認(rèn)如果開啟RDB快照(至少一條save指令)并且最新的后臺(tái)保存失敗,Redis將會(huì)停止接受寫操作
# 這將使用戶知道數(shù)據(jù)沒(méi)有正確的持久化到硬盤,否則可能沒(méi)人注意到并且造成一些災(zāi)難
stop-writes-on-bgsave-error yes
# 默認(rèn)如果開啟RDB快照(至少一條save指令)并且最新的后臺(tái)保存失敗,Redis將會(huì)停止接受寫操作。
stop-writes-on-bgsave-error yes
# 當(dāng)導(dǎo)出到 .rdb 數(shù)據(jù)庫(kù)時(shí)是否用LZF壓縮字符串對(duì)象
rdbcompression yes
# 版本5的RDB有一個(gè)CRC64算法的校驗(yàn)和放在了文件的最后。這將使文件格式更加可靠。
rdbchecksum yes
# 持久化數(shù)據(jù)庫(kù)的文件名
dbfilename dump-master.rdb
# 工作目錄
dir /usr/local/redis-4.0.8/redis_master/
# slav服務(wù)連接master的密碼
masterauth testmaster123
# 當(dāng)一個(gè)slave失去和master的連接,或者同步正在進(jìn)行中,slave的行為可以有兩種:
#1) 如果 slave-serve-stale-data 設(shè)置為 "yes" (默認(rèn)值),slave會(huì)繼續(xù)響應(yīng)客戶端請(qǐng)求,可能是正常數(shù)據(jù),或者是過(guò)時(shí)了的數(shù)據(jù),也可能是還沒(méi)獲得值的空數(shù)據(jù)。
# 2) 如果 slave-serve-stale-data 設(shè)置為 "no",slave會(huì)回復(fù)"正在從master同步
# (SYNC with master in progress)"來(lái)處理各種請(qǐng)求,除了 INFO 和 SLAVEOF 命令。
slave-serve-stale-data yes
# 配置是否僅讀
slave-read-only yes
# 如果你選擇“yes”Redis將使用更少的TCP包和帶寬來(lái)向slaves發(fā)送數(shù)據(jù)。但是這將使數(shù)據(jù)傳輸?shù)絪lave上有延遲,Linux內(nèi)核的默認(rèn)配置會(huì)達(dá)到40毫秒
# 如果你選擇了 "no" 數(shù)據(jù)傳輸?shù)絪alve的延遲將會(huì)減少但要使用更多的帶寬
repl-disable-tcp-nodelay no
# slave的優(yōu)先級(jí),優(yōu)先級(jí)數(shù)字小的salve會(huì)優(yōu)先考慮提升為master
slave-priority 100
# 密碼驗(yàn)證
requirepass testmaster123
# redis實(shí)例最大占用內(nèi)存,一旦內(nèi)存使用達(dá)到上限,Redis會(huì)根據(jù)選定的回收策略(參見(jiàn):
# maxmemmory-policy)刪除key
maxmemory 3gb
# 最大內(nèi)存策略:如果達(dá)到內(nèi)存限制了,Redis如何選擇刪除key。
# volatile-lru -> 根據(jù)LRU算法刪除帶有過(guò)期時(shí)間的key。
# allkeys-lru -> 根據(jù)LRU算法刪除任何key。
# volatile-random -> 根據(jù)過(guò)期設(shè)置來(lái)隨機(jī)刪除key, 具備過(guò)期時(shí)間的key。 
# allkeys->random -> 無(wú)差別隨機(jī)刪, 任何一個(gè)key。 
# volatile-ttl -> 根據(jù)最近過(guò)期時(shí)間來(lái)刪除(輔以TTL), 這是對(duì)于有過(guò)期時(shí)間的key 
# noeviction -> 誰(shuí)也不刪,直接在寫操作時(shí)返回錯(cuò)誤。
maxmemory-policy volatile-lru
# AOF開啟
appendonly no
# aof文件名
appendfilename "appendonly.aof"
# fsync() 系統(tǒng)調(diào)用告訴操作系統(tǒng)把數(shù)據(jù)寫到磁盤上,而不是等更多的數(shù)據(jù)進(jìn)入輸出緩沖區(qū)。
# 有些操作系統(tǒng)會(huì)真的把數(shù)據(jù)馬上刷到磁盤上;有些則會(huì)盡快去嘗試這么做。
# Redis支持三種不同的模式:
# no:不要立刻刷,只有在操作系統(tǒng)需要刷的時(shí)候再刷。比較快。
# always:每次寫操作都立刻寫入到aof文件。慢,但是最安全。
# everysec:每秒寫一次。折中方案。 
appendfsync everysec
# 如果AOF的同步策略設(shè)置成 "always" 或者 "everysec",并且后臺(tái)的存儲(chǔ)進(jìn)程(后臺(tái)存儲(chǔ)或?qū)懭階OF
# 日志)會(huì)產(chǎn)生很多磁盤I/O開銷。某些Linux的配置下會(huì)使Redis因?yàn)?fsync()系統(tǒng)調(diào)用而阻塞很久。
# 注意,目前對(duì)這個(gè)情況還沒(méi)有完美修正,甚至不同線程的 fsync() 會(huì)阻塞我們同步的write(2)調(diào)用。
# 為了緩解這個(gè)問(wèn)題,可以用下面這個(gè)選項(xiàng)。它可以在 BGSAVE 或 BGREWRITEAOF 處理時(shí)阻止主進(jìn)程進(jìn)行fsync()。
# 這就意味著如果有子進(jìn)程在進(jìn)行保存操作,那么Redis就處于"不可同步"的狀態(tài)。
# 這實(shí)際上是說(shuō),在最差的情況下可能會(huì)丟掉30秒鐘的日志數(shù)據(jù)。(默認(rèn)Linux設(shè)定)
# 如果你有延時(shí)問(wèn)題把這個(gè)設(shè)置成"yes",否則就保持"no",這是保存持久數(shù)據(jù)的最安全的方式。
no-appendfsync-on-rewrite yes
# 自動(dòng)重寫AOF文件
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# AOF文件可能在尾部是不完整的(這跟system關(guān)閉有問(wèn)題,尤其是mount ext4文件系統(tǒng)時(shí)
# 沒(méi)有加上data=ordered選項(xiàng)。只會(huì)發(fā)生在os死時(shí),redis自己死不會(huì)不完整)。
# 那redis重啟時(shí)load進(jìn)內(nèi)存的時(shí)候就有問(wèn)題了。
# 發(fā)生的時(shí)候,可以選擇redis啟動(dòng)報(bào)錯(cuò),并且通知用戶和寫日志,或者load盡量多正常的數(shù)據(jù)。
# 如果aof-load-truncated是yes,會(huì)自動(dòng)發(fā)布一個(gè)log給客戶端然后load(默認(rèn))。
# 如果是no,用戶必須手動(dòng)redis-check-aof修復(fù)AOF文件才可以。
# 注意,如果在讀取的過(guò)程中,發(fā)現(xiàn)這個(gè)aof是損壞的,服務(wù)器也是會(huì)退出的,
# 這個(gè)選項(xiàng)僅僅用于當(dāng)服務(wù)器嘗試讀取更多的數(shù)據(jù)但又找不到相應(yīng)的數(shù)據(jù)時(shí)。
aof-load-truncated yes
# Lua 腳本的最大執(zhí)行時(shí)間,毫秒為單位
lua-time-limit 5000
# Redis慢查詢?nèi)罩究梢杂涗洺^(guò)指定時(shí)間的查詢
slowlog-log-slower-than 10000
# 這個(gè)長(zhǎng)度沒(méi)有限制。只是要主要會(huì)消耗內(nèi)存。你可以通過(guò) SLOWLOG RESET 來(lái)回收內(nèi)存。
slowlog-max-len 128
# 客戶端的輸出緩沖區(qū)的限制,可用于強(qiáng)制斷開那些因?yàn)槟撤N原因從服務(wù)器讀取數(shù)據(jù)的速度不夠快的客戶端
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
# 當(dāng)一個(gè)子進(jìn)程重寫AOF文件時(shí),文件每生成32M數(shù)據(jù)會(huì)被同步
aof-rewrite-incremental-fsync yes
 

由于,單機(jī)版的Redis在并發(fā)量比較大的時(shí)候,并且需要較高性能和可靠性的時(shí)候,單機(jī)版基本就不適合了,于是就出現(xiàn)了「主從模式」。

 

主從模式

 

原理

主從的原理還算是比較簡(jiǎn)單的,一主多從,「主數(shù)據(jù)庫(kù)(master)可以讀也可以寫(read/write),從數(shù)據(jù)庫(kù)僅讀(only read)」。

但是,主從模式一般實(shí)現(xiàn)「讀寫分離」,「主數(shù)據(jù)庫(kù)僅寫(only write)」,減輕主數(shù)據(jù)庫(kù)的壓力,下面一張圖搞懂主從模式的原理:

Redis主從復(fù)制、哨兵、Cluster三種模式詳細(xì)介紹  

主從模式原理就是那么簡(jiǎn)單,那他執(zhí)行的過(guò)程(工作機(jī)制)又是怎么樣的呢?再來(lái)一張圖:

Redis主從復(fù)制、哨兵、Cluster三種模式詳細(xì)介紹當(dāng)開啟主從模式的時(shí)候,他的具體工作機(jī)制如下:

  1. 當(dāng)slave啟動(dòng)后會(huì)向master發(fā)送     SYNC命令,master節(jié)點(diǎn)收到從數(shù)據(jù)庫(kù)的命令后通過(guò)     bgsave保存快照(     「RDB持久化」),并且期間的執(zhí)行的些命令會(huì)被緩存起來(lái)。
  2. 然后master會(huì)將保存的快照發(fā)送給slave,并且繼續(xù)緩存期間的寫命令。
  3. slave收到主數(shù)據(jù)庫(kù)發(fā)送過(guò)來(lái)的快照就會(huì)加載到自己的數(shù)據(jù)庫(kù)中。
  4. 最后master講緩存的命令同步給slave,slave收到命令后執(zhí)行一遍,這樣master與slave數(shù)據(jù)就保持一致了。
 

優(yōu)點(diǎn)

之所以運(yùn)用主從,是因?yàn)橹鲝囊欢ǔ潭壬辖鉀Q了單機(jī)版并發(fā)量大,導(dǎo)致請(qǐng)求延遲或者redis宕機(jī)服務(wù)停止的問(wèn)題。

從數(shù)據(jù)庫(kù)分擔(dān)主數(shù)據(jù)庫(kù)的讀壓力,若是主數(shù)據(jù)庫(kù)是只寫模式,那么實(shí)現(xiàn)讀寫分離,主數(shù)據(jù)庫(kù)就沒(méi)有了讀壓力了。

另一方面解決了單機(jī)版單點(diǎn)故障的問(wèn)題,若是主數(shù)據(jù)庫(kù)掛了,那么從數(shù)據(jù)庫(kù)可以隨時(shí)頂上來(lái),綜上來(lái)說(shuō),主從模式一定程度上提高了系統(tǒng)的可用性和性能,是實(shí)現(xiàn)哨兵和集群的基礎(chǔ)。

主從同步以異步方式進(jìn)行同步,期間Redis仍然可以響應(yīng)客戶端提交的查詢和更新的請(qǐng)求。

 

缺點(diǎn)

主從模式好是好,他也有自己的缺點(diǎn),比如數(shù)據(jù)的一致性問(wèn)題,假如主數(shù)據(jù)庫(kù)寫操作完成,那么他的數(shù)據(jù)會(huì)被復(fù)制到從數(shù)據(jù)庫(kù),若是還沒(méi)有即使復(fù)制到從數(shù)據(jù)庫(kù),讀請(qǐng)求又來(lái)了,此時(shí)讀取的數(shù)據(jù)就不是最新的數(shù)據(jù)。

若是從主同步的過(guò)程網(wǎng)絡(luò)出故障了,導(dǎo)致主從同步失敗,也會(huì)出現(xiàn)問(wèn)題數(shù)據(jù)一致性的問(wèn)題。

主從模式不具備自動(dòng)容錯(cuò)和恢復(fù)的功能,一旦主數(shù)據(jù)庫(kù),從節(jié)點(diǎn)晉升為主數(shù)據(jù)庫(kù)的過(guò)程需要人為操作,維護(hù)的成本就會(huì)升高,并且主節(jié)點(diǎn)的寫能力、存儲(chǔ)能力都會(huì)受到限制。

 

實(shí)操搭建

下面的我們來(lái)實(shí)操搭建一下主從模式,主從模式的搭建還是比較簡(jiǎn)單的,我這里一臺(tái)centos 7虛擬機(jī),使用開啟redis多實(shí)例的方法搭建主從。

redis中開啟多實(shí)例的方法,首先創(chuàng)建一個(gè)文件夾,用于存放redis集群的配置文件:

mkdir redis
 

然后粘貼復(fù)制redis.conf配置文件:

cp /root/redis-4.0.6/redis.conf /root/redis/redis-6379.conf
cp /root/redis-4.0.6/redis.conf /root/redis/redis-6380.conf
cp /root/redis-4.0.6/redis.conf /root/redis/redis-6381.conf
 

復(fù)制三份配置文件,一主兩從,6379端口作為主數(shù)據(jù)庫(kù)(master),6380、6381作為從數(shù)據(jù)庫(kù)(slave)。

首先是配置主數(shù)據(jù)庫(kù)的配置文件:vi redis-6379.conf

bind 0.0.0.0 # 注釋掉或配置成0.0.0.0表示任意IP均可訪問(wèn)。
protected-mode no # 關(guān)閉保護(hù)模式,使用密碼訪問(wèn)。
port 6379  # 設(shè)置端口,6380、6381依次為6380、6381。
timeout 30 # 客戶端連接空閑多久后斷開連接,單位秒,0表示禁用
daemonize yes # 在后臺(tái)運(yùn)行
pidfile /var/run/redis_6379.pid  # pid進(jìn)程文件名,6380、6381依次為redis_6380.pid、redis_6381.pid
logfile /root/reids/log/6379.log # 日志文件,6380、6381依次為6380.log、6381.log
save 900 1 # 900s內(nèi)至少一次寫操作則執(zhí)行bgsave進(jìn)行RDB持久化
save 300 10
save 60 10000 
rdbcompression yes #是否對(duì)RDB文件進(jìn)行壓縮,建議設(shè)置為no,以(磁盤)空間換(CPU)時(shí)間
dbfilename dump.rdb # RDB文件名稱
dir /root/redis/datas # RDB文件保存路徑,AOF文件也保存在這里
appendonly yes # 表示使用AOF增量持久化的方式
appendfsync everysec # 可選值 always, everysec,no,建議設(shè)置為everysec
requirepass 123456 # 設(shè)置密碼
 

然后,就是修改從數(shù)據(jù)庫(kù)的配置文件,在從數(shù)據(jù)庫(kù)的配置文件中加入以下的配置信息:

slaveof 127.0.0.1 6379 # 配置master的ip,port
masterauth 123456 # 配置訪問(wèn)master的密碼
slaveof-serve-stale-data no 
 

接下來(lái)就是啟動(dòng)三個(gè)redis實(shí)例,啟動(dòng)的命令,先cd到redis的src目錄下,然后執(zhí)行:

./redis-server /root/redis/6379.conf
./redis-server /root/redis/6380.conf
./redis-server /root/redis/6381.conf
 

通過(guò)命令ps -aux | grep redis,查看啟動(dòng)的redis進(jìn)程:Redis主從復(fù)制、哨兵、Cluster三種模式詳細(xì)介紹如上圖所示,表示啟動(dòng)成功,下面就開始進(jìn)入測(cè)試階段。

 

測(cè)試

我這里使用SecureCRT作為redis連接的客戶端,同時(shí)啟動(dòng)三個(gè)SecureCRT,分別連接redis1的三個(gè)實(shí)例,啟動(dòng)時(shí)指定端口以及密碼:

./redis-cli -p 6379 -a 123456
 

Redis主從復(fù)制、哨兵、Cluster三種模式詳細(xì)介紹啟動(dòng)后,在master(6379),輸入:set name 'ldc',在slave中通過(guò)get name,可以查看:

Redis主從復(fù)制、哨兵、Cluster三種模式詳細(xì)介紹數(shù)據(jù)同步成功,這有幾個(gè)坑一個(gè)是redis.conf中沒(méi)有設(shè)置對(duì)bind,會(huì)導(dǎo)致非本機(jī)的ip被過(guò)濾掉,一般配置0.0.0.0就可以了。

另一個(gè)是沒(méi)有配置密碼requirepass 123456,會(huì)導(dǎo)致IO一直連接異常,這個(gè)是我遇到的坑,后面配置密碼后就成功了。

還有,就是查看redis的啟動(dòng)日志可以發(fā)現(xiàn)有兩個(gè)warning,雖然不影響搭建主從同步,看著挺煩人的,但是有些人會(huì)遇到,有些人不會(huì)遇到。

但是,我這個(gè)人比較有強(qiáng)迫癥,百度也是有解決方案的,這里就不講了,交給你們自己解決,這里只是告訴你有這個(gè)問(wèn)題,有些人看都不看日志的,看到啟動(dòng)成功就認(rèn)為萬(wàn)事大吉了,也不看日志,這習(xí)慣并不好。

Redis主從復(fù)制、哨兵、Cluster三種模式詳細(xì)介紹  
 

哨兵模式

 

原理

哨兵模式是主從的升級(jí)版,因?yàn)橹鲝牡某霈F(xiàn)故障后,不會(huì)自動(dòng)恢復(fù),需要人為干預(yù),這就很蛋疼啊。

在主從的基礎(chǔ)上,實(shí)現(xiàn)哨兵模式就是為了監(jiān)控主從的運(yùn)行狀況,對(duì)主從的健壯進(jìn)行監(jiān)控,就好像哨兵一樣,只要有異常就發(fā)出警告,對(duì)異常狀況進(jìn)行處理。

Redis主從復(fù)制、哨兵、Cluster三種模式詳細(xì)介紹所以,總的概括來(lái)說(shuō),哨兵模式有以下的優(yōu)點(diǎn)(功能點(diǎn)):

  1. 「監(jiān)控」:監(jiān)控master和slave是否正常運(yùn)行,以及哨兵之間也會(huì)相互監(jiān)控
  2. 「自動(dòng)故障恢復(fù)」:當(dāng)master出現(xiàn)故障的時(shí)候,會(huì)自動(dòng)選舉一個(gè)slave作為master頂上去。

哨兵模式的監(jiān)控配置信息,是通過(guò)配置從數(shù)據(jù)庫(kù)的sentinel monitor <master-name> <ip> <redis-port> <quorum> 來(lái)指定的,比如:

// mymaster 表示給master數(shù)據(jù)庫(kù)定義了一個(gè)名字,后面的是master的ip和端口,1表示至少需要一個(gè)Sentinel進(jìn)程同意才能將master判斷為失效,如果不滿足這個(gè)條件,則自動(dòng)故障轉(zhuǎn)移(failover)不會(huì)執(zhí)行
sentinel monitor mymaster 127.0.0.1 6379 1
   

節(jié)點(diǎn)通信

當(dāng)然還有其它的配置信息,其它配置信息,在環(huán)境搭建的時(shí)候再說(shuō)。當(dāng)哨兵啟動(dòng)后,會(huì)與master建立一條連接,用于訂閱master的_sentinel_:hello頻道。

該頻道用于獲取監(jiān)控該master的其它哨兵的信息。并且還會(huì)建立一條定時(shí)向master發(fā)送INFO命令獲取master信息的連接。

「當(dāng)哨兵與master建立連接后,定期會(huì)向(10秒一次)master和slave發(fā)送INFO命令,若是master被標(biāo)記為主觀下線,頻率就會(huì)變?yōu)?秒一次?!?/strong>

并且,定期向_sentinel_:hello頻道發(fā)送自己的信息,以便其它的哨兵能夠訂閱獲取自己的信息,發(fā)送的內(nèi)容包含「哨兵的ip和端口、運(yùn)行id、配置版本、master名字、master的ip端口還有master的配置版本」等信息。

以及,「定期的向master、slave和其它哨兵發(fā)送PING命令(每秒一次),以便檢測(cè)對(duì)象是否存活」,若是對(duì)方接收到了PING命令,無(wú)故障情況下,會(huì)回復(fù)PONG命令。

所以,哨兵通過(guò)建立這兩條連接、通過(guò)定期發(fā)送INFO、PING命令來(lái)實(shí)現(xiàn)哨兵與哨兵、哨兵與master之間的通信。

這里涉及到一些概念需要理解,INFO、PING、PONG等命令,后面還會(huì)有MEET、FAIL命令,以及主觀下線,當(dāng)然還會(huì)有客觀下線,這里主要說(shuō)一下這幾個(gè)概念的理解:

  1. INFO:該命令可以獲取主從數(shù)據(jù)庫(kù)的最新信息,可以實(shí)現(xiàn)新結(jié)點(diǎn)的發(fā)現(xiàn)
  2. PING:該命令被使用最頻繁,該命令封裝了自身節(jié)點(diǎn)和其它節(jié)點(diǎn)的狀態(tài)數(shù)據(jù)。
  3. PONG:當(dāng)節(jié)點(diǎn)收到MEET和PING,會(huì)回復(fù)PONG命令,也把自己的狀態(tài)發(fā)送給對(duì)方。
  4. MEET:該命令在新結(jié)點(diǎn)加入集群的時(shí)候,會(huì)向老節(jié)點(diǎn)發(fā)送該命令,表示自己是個(gè)新人
  5. FAIL:當(dāng)節(jié)點(diǎn)下線,會(huì)向集群中廣播該消息。
 

上線和下線

當(dāng)哨兵與master相同之后就會(huì)定期一直保持聯(lián)系,若是某一時(shí)刻哨兵發(fā)送的PING在指定時(shí)間內(nèi)沒(méi)有收到回復(fù)(sentinel down-after-milliseconds master-name milliseconds 配置),那么發(fā)送PING命令的哨兵就會(huì)認(rèn)為該master「主觀下線」Subjectively Down)。

因?yàn)橛锌赡苁巧诒c該master之間的網(wǎng)絡(luò)問(wèn)題造成的,而不是master本身的原因,所以哨兵同時(shí)會(huì)詢問(wèn)其它的哨兵是否也認(rèn)為該master下線,若是認(rèn)為該節(jié)點(diǎn)下線的哨兵達(dá)到一定的數(shù)量(「前面的quorum字段配置」),就會(huì)認(rèn)為該節(jié)點(diǎn)「客觀下線」Objectively Down)。

若是沒(méi)有足夠數(shù)量的sentinel同意該master下線,則該master客觀下線的標(biāo)識(shí)會(huì)被移除;若是master重新向哨兵的PING命令回復(fù)了客觀下線的標(biāo)識(shí)也會(huì)被移除。

 

選舉算法

當(dāng)master被認(rèn)為客觀下線后,又是怎么進(jìn)行故障恢復(fù)的呢?原來(lái)哨兵中首先選舉出一個(gè)老大哨兵來(lái)進(jìn)行故障恢復(fù),選舉老大哨兵的算法叫做「Raft算法」

  1. 發(fā)現(xiàn)master下線的哨兵(sentinelA)會(huì)向其它的哨兵發(fā)送命令進(jìn)行拉票,要求選擇自己為哨兵大佬。
  2. 若是目標(biāo)哨兵沒(méi)有選擇其它的哨兵,就會(huì)選擇該哨兵(sentinelA)為大佬。
  3. 若是選擇sentinelA的哨兵超過(guò)半數(shù)(半數(shù)原則),該大佬非sentinelA莫屬。
  4. 如果有多個(gè)哨兵同時(shí)競(jìng)選,并且可能存在票數(shù)一致的情況,就會(huì)等待下次的一個(gè)隨機(jī)時(shí)間再次發(fā)起競(jìng)選請(qǐng)求,進(jìn)行新的一輪投票,直到大佬被選出來(lái)。

選出大佬哨兵后,大佬哨兵就會(huì)對(duì)故障進(jìn)行自動(dòng)回復(fù),從slave中選出一名slave作為主數(shù)據(jù)庫(kù),選舉的規(guī)則如下所示:

  1. 所有的slave中     slave-priority優(yōu)先級(jí)最高的會(huì)被選中。
  2. 若是優(yōu)先級(jí)相同,會(huì)選擇偏移量最大的,因?yàn)槠屏坑涗浿鴶?shù)據(jù)的復(fù)制的增量,越大表示數(shù)據(jù)越完整。
  3. 若是以上兩者都相同,選擇ID最小的。

通過(guò)以上的層層篩選最終實(shí)現(xiàn)故障恢復(fù),當(dāng)選的slave晉升為master,其它的slave會(huì)向新的master復(fù)制數(shù)據(jù),若是down掉的master重新上線,會(huì)被當(dāng)作slave角色運(yùn)行。

 

優(yōu)點(diǎn)

哨兵模式是主從模式的升級(jí)版,所以在系統(tǒng)層面提高了系統(tǒng)的可用性和性能、穩(wěn)定性。當(dāng)master宕機(jī)的時(shí)候,能夠自動(dòng)進(jìn)行故障恢復(fù),需不要人為的干預(yù)。

哨兵與哨兵之間、哨兵與master之間能夠進(jìn)行及時(shí)的監(jiān)控,心跳檢測(cè),及時(shí)發(fā)現(xiàn)系統(tǒng)的問(wèn)題,這都是彌補(bǔ)了主從的缺點(diǎn)。

 

缺點(diǎn)

哨兵一主多從的模式同樣也會(huì)遇到寫的瓶頸,已經(jīng)存儲(chǔ)瓶頸,若是master宕機(jī)了,故障恢復(fù)的時(shí)間比較長(zhǎng),寫的業(yè)務(wù)就會(huì)受到影響。

增加了哨兵也增加了系統(tǒng)的復(fù)雜度,需要同時(shí)維護(hù)哨兵模式。

 

實(shí)操搭建

最后,我們進(jìn)行一下哨兵模式的搭建,配置哨兵模式還是比較簡(jiǎn)單的,在上面配置的主從模式的基礎(chǔ)上,同時(shí)創(chuàng)建一個(gè)文件夾用于存放三個(gè)哨兵的配置文件:

mkdir /root/redis-4.0.6/sentinel.conf  /root/redis/sentinel/sentinel1.conf 
mkdir /root/redis-4.0.6/sentinel.conf  /root/redis/sentinel/sentinel2.conf 
mkdir /root/redis-4.0.6/sentinel.conf  /root/redis/sentinel/sentinel3.conf 
 

分別在這三個(gè)文件中添加如下配置:

daemonize yes # 在后臺(tái)運(yùn)行
sentinel monitor mymaster 127.0.0.1 6379 1 # 給master起一個(gè)名字mymaster,并且配置master的ip和端口
sentinel auth-pass mymaster 123456 # master的密碼
port 26379 #另外兩個(gè)配置36379,46379端口
sentinel down-after-milliseconds mymaster 3000 # 3s未回復(fù)PING就認(rèn)為master主觀下線
sentinel parallel-syncs mymaster 2  # 執(zhí)行故障轉(zhuǎn)移時(shí),最多可以有2個(gè)slave實(shí)例在同步新的master實(shí)例
sentinel failover-timeout mymaster 100000 # 如果在10s內(nèi)未能完成故障轉(zhuǎn)移操作認(rèn)為故障轉(zhuǎn)移失敗
 

配置完后分別啟動(dòng)三臺(tái)哨兵:

./redis-server sentinel1.conf --sentinel
./redis-server sentinel2.conf --sentinel
./redis-server sentinel3.conf --sentinel
 

然后通過(guò):ps -aux|grep redis進(jìn)行查看:Redis主從復(fù)制、哨兵、Cluster三種模式詳細(xì)介紹可以看到三臺(tái)redis實(shí)例以及三個(gè)哨兵都已經(jīng)正常啟動(dòng),現(xiàn)登陸6379,通過(guò)INFO Repliaction查看master信息:

Redis主從復(fù)制、哨兵、Cluster三種模式詳細(xì)介紹當(dāng)前master為6379,然后我們來(lái)測(cè)試一下哨兵的自動(dòng)故障恢復(fù),直接kill掉6379進(jìn)程,然后通過(guò)登陸6380再次查看master的信息:

Redis主從復(fù)制、哨兵、Cluster三種模式詳細(xì)介紹可以看到當(dāng)前的6380角色是master,并且6380可讀可寫,而不是只讀模式,這說(shuō)明我們的哨兵是起作用了,搭建成功,感興趣的可以自行搭建,也有可能你會(huì)踩一堆的坑。

 

Cluster模式

最后,Cluster是真正的集群模式了,哨兵解決和主從不能自動(dòng)故障恢復(fù)的問(wèn)題,但是同時(shí)也存在難以擴(kuò)容以及單機(jī)存儲(chǔ)、讀寫能力受限的問(wèn)題,并且集群之前都是一臺(tái)redis都是全量的數(shù)據(jù),這樣所有的redis都冗余一份,就會(huì)大大消耗內(nèi)存空間。

集群模式實(shí)現(xiàn)了Redis數(shù)據(jù)的分布式存儲(chǔ),實(shí)現(xiàn)數(shù)據(jù)的分片,每個(gè)redis節(jié)點(diǎn)存儲(chǔ)不同的內(nèi)容,并且解決了在線的節(jié)點(diǎn)收縮(下線)和擴(kuò)容(上線)問(wèn)題。

集群模式真正意義上實(shí)現(xiàn)了系統(tǒng)的高可用和高性能,但是集群同時(shí)進(jìn)一步使系統(tǒng)變得越來(lái)越復(fù)雜,接下來(lái)我們來(lái)詳細(xì)的了解集群的運(yùn)作原理。

 

數(shù)據(jù)分區(qū)原理

集群的原理圖還是很好理解的,在Redis集群中采用的是虛擬槽分區(qū)算法,會(huì)把redis集群分成16384 個(gè)槽(0 -16383)。

比如:下圖所示三個(gè)master,會(huì)把0 -16383范圍的槽可能分成三部分(0-5000)、(5001-11000)、(11001-16383)分別數(shù)據(jù)三個(gè)緩存節(jié)點(diǎn)的槽范圍。

Redis主從復(fù)制、哨兵、Cluster三種模式詳細(xì)介紹當(dāng)客戶端請(qǐng)求過(guò)來(lái),會(huì)首先通過(guò)對(duì)key進(jìn)行CRC16 校驗(yàn)并對(duì) 16384 取模(CRC16(key)%16383)計(jì)算出key所在的槽,然后再到對(duì)應(yīng)的槽上進(jìn)行取數(shù)據(jù)或者存數(shù)據(jù),這樣就實(shí)現(xiàn)了數(shù)據(jù)的訪問(wèn)更新。

Redis主從復(fù)制、哨兵、Cluster三種模式詳細(xì)介紹  

之所以進(jìn)行分槽存儲(chǔ),是將一整堆的數(shù)據(jù)進(jìn)行分片,防止單臺(tái)的redis數(shù)據(jù)量過(guò)大,影響性能的問(wèn)題。

 

節(jié)點(diǎn)通信

節(jié)點(diǎn)之間實(shí)現(xiàn)了將數(shù)據(jù)進(jìn)行分片存儲(chǔ),那么節(jié)點(diǎn)之間又是怎么通信的呢?這個(gè)和前面哨兵模式講的命令基本一樣。

首先新上線的節(jié)點(diǎn),會(huì)通過(guò) Gossip 協(xié)議向老成員發(fā)送Meet消息,表示自己是新加入的成員。

老成員收到Meet消息后,在沒(méi)有故障的情況下會(huì)恢復(fù)PONG消息,表示歡迎新結(jié)點(diǎn)的加入,除了第一次發(fā)送Meet消息后,之后都會(huì)發(fā)送定期PING消息,實(shí)現(xiàn)節(jié)點(diǎn)之間的通信。

Redis主從復(fù)制、哨兵、Cluster三種模式詳細(xì)介紹  

通信的過(guò)程中會(huì)為每一個(gè)通信的節(jié)點(diǎn)開通一條tcp通道,之后就是定時(shí)任務(wù),不斷的向其它節(jié)點(diǎn)發(fā)送PING消息,這樣做的目的就是為了了解節(jié)點(diǎn)之間的元數(shù)據(jù)存儲(chǔ)情況,以及健康狀況,以便即使發(fā)現(xiàn)問(wèn)題。

 

數(shù)據(jù)請(qǐng)求

上面說(shuō)到了槽信息,在Redis的底層維護(hù)了unsigned char myslots[CLUSTER_SLOTS/8] 一個(gè)數(shù)組存放每個(gè)節(jié)點(diǎn)的槽信息。

因?yàn)樗且粋€(gè)二進(jìn)制數(shù)組,只有存儲(chǔ)0和1值,如下圖所示:

Redis主從復(fù)制、哨兵、Cluster三種模式詳細(xì)介紹  

這樣數(shù)組只表示自己是否存儲(chǔ)對(duì)應(yīng)的槽數(shù)據(jù),若是1表示存在該數(shù)據(jù),0表示不存在該數(shù)據(jù),這樣查詢的效率就會(huì)非常的高,類似于布隆過(guò)濾器,二進(jìn)制存儲(chǔ)。

比如:集群節(jié)點(diǎn)1負(fù)責(zé)存儲(chǔ)0-5000的槽數(shù)據(jù),但是此時(shí)只有0、1、2存儲(chǔ)有數(shù)據(jù),其它的槽還沒(méi)有存數(shù)據(jù),所以0、1、2對(duì)應(yīng)的值為1。

并且,每個(gè)redis底層還維護(hù)了一個(gè)clusterNode數(shù)組,大小也是16384,用于儲(chǔ)存負(fù)責(zé)對(duì)應(yīng)槽的節(jié)點(diǎn)的ip、端口等信息,這樣每一個(gè)節(jié)點(diǎn)就維護(hù)了其它節(jié)點(diǎn)的元數(shù)據(jù)信息,便于及時(shí)的找到對(duì)應(yīng)的節(jié)點(diǎn)。

當(dāng)新結(jié)點(diǎn)加入或者節(jié)點(diǎn)收縮,通過(guò)PING命令通信,及時(shí)的更新自己clusterNode數(shù)組中的元數(shù)據(jù)信息,這樣有請(qǐng)求過(guò)來(lái)也就能及時(shí)的找到對(duì)應(yīng)的節(jié)點(diǎn)。

Redis主從復(fù)制、哨兵、Cluster三種模式詳細(xì)介紹有兩種其它的情況就是,若是請(qǐng)求過(guò)來(lái)發(fā)現(xiàn),數(shù)據(jù)發(fā)生了遷移,比如新節(jié)點(diǎn)加入,會(huì)使舊的緩存節(jié)點(diǎn)數(shù)據(jù)遷移到新結(jié)點(diǎn)。

請(qǐng)求過(guò)來(lái)發(fā)現(xiàn)舊節(jié)點(diǎn)已經(jīng)發(fā)生了數(shù)據(jù)遷移并且數(shù)據(jù)被遷移到新結(jié)點(diǎn),由于每個(gè)節(jié)點(diǎn)都有clusterNode信息,通過(guò)該信息的ip和端口。此時(shí)舊節(jié)點(diǎn)就會(huì)向客戶端發(fā)一個(gè)MOVED 的重定向請(qǐng)求,表示數(shù)據(jù)已經(jīng)遷移到新結(jié)點(diǎn)上,你要訪問(wèn)這個(gè)新結(jié)點(diǎn)的ip和端口就能拿到數(shù)據(jù),這樣就能重新獲取到數(shù)據(jù)。

倘若正在發(fā)正數(shù)據(jù)遷移呢?舊節(jié)點(diǎn)就會(huì)向客戶端發(fā)送一個(gè)ASK 重定向請(qǐng)求,并返回給客戶端遷移的目標(biāo)節(jié)點(diǎn)的ip和端口,這樣也能獲取到數(shù)據(jù)。

 

擴(kuò)容和收縮

擴(kuò)容和收縮也就是節(jié)點(diǎn)的上線和下線,可能節(jié)點(diǎn)發(fā)生故障了,故障自動(dòng)回復(fù)的過(guò)程(節(jié)點(diǎn)收縮)。

節(jié)點(diǎn)的收縮和擴(kuò)容時(shí),會(huì)重新計(jì)算每一個(gè)節(jié)點(diǎn)負(fù)責(zé)的槽范圍,并發(fā)根據(jù)虛擬槽算法,將對(duì)應(yīng)的數(shù)據(jù)更新到對(duì)應(yīng)的節(jié)點(diǎn)。

還有前面的講的新加入的節(jié)點(diǎn)會(huì)首先發(fā)送Meet消息,詳細(xì)可以查看前面講的內(nèi)容,基本一樣的模式。

以及發(fā)生故障后,哨兵老大節(jié)點(diǎn)的選舉,master節(jié)點(diǎn)的重新選舉,slave怎樣晉升為master節(jié)點(diǎn),可以查看前面哨兵模式選舉過(guò)程。

 

優(yōu)點(diǎn)

集群模式是一個(gè)無(wú)中心的架構(gòu)模式,將數(shù)據(jù)進(jìn)行分片,分布到對(duì)應(yīng)的槽中,每個(gè)節(jié)點(diǎn)存儲(chǔ)不同的數(shù)據(jù)內(nèi)容,通過(guò)路由能夠找到對(duì)應(yīng)的節(jié)點(diǎn)負(fù)責(zé)存儲(chǔ)的槽,能夠?qū)崿F(xiàn)高效率的查詢。

并且集群模式增加了橫向和縱向的擴(kuò)展能力,實(shí)現(xiàn)節(jié)點(diǎn)加入和收縮,集群模式是哨兵的升級(jí)版,哨兵的優(yōu)點(diǎn)集群都有。

 

缺點(diǎn)

緩存的最大問(wèn)題就是帶來(lái)數(shù)據(jù)一致性問(wèn)題,在平衡數(shù)據(jù)一致性的問(wèn)題時(shí),兼顧性能與業(yè)務(wù)要求,大多數(shù)都是以最終一致性的方案進(jìn)行解決,而不是強(qiáng)一致性。

并且集群模式帶來(lái)節(jié)點(diǎn)數(shù)量的劇增,一個(gè)集群模式最少要6臺(tái)機(jī),因?yàn)橐獫M足半數(shù)原則的選舉方式,所以也帶來(lái)了架構(gòu)的復(fù)雜性。

slave只充當(dāng)冷備,并不能緩解master的讀的壓力。

 

實(shí)操搭建

集群模式的部署比較簡(jiǎn)單,只要在redis.conf加入下面的配置信息即可:

port 6379# 本示例6個(gè)節(jié)點(diǎn)端口分別為6379、6380、6381、6382、6383、6384
daemonize yes # r后臺(tái)運(yùn)行 
pidfile /var/run/redis_6379.pid # 分別對(duì)應(yīng)6379、6380、6381、6382、6383、6384
cluster-enabled yes # 開啟集群模式 
masterauth 123456# 如果設(shè)置了密碼,需要指定master密碼
cluster-config-file nodes_6379.conf # 集群的配置文件,同樣對(duì)應(yīng)6379、6380、6381、6382、6383、6384六個(gè)節(jié)點(diǎn)
cluster-node-timeout 10000 # 請(qǐng)求超時(shí)時(shí)間
 

同時(shí)開啟這六個(gè)實(shí)例,通過(guò)下面的命令將這六個(gè)實(shí)例以集群的方式運(yùn)行

./redis-cli --cluster create --cluster-replicas 1 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381  127.0.0.1:6382  127.0.0.1:6383  127.0.0.1:6384  -a 123456

感謝各位的閱讀,以上就是“Redis主從復(fù)制、哨兵、Cluster三種模式詳細(xì)介紹”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)Redis主從復(fù)制、哨兵、Cluster三種模式詳細(xì)介紹這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

新聞標(biāo)題:Redis主從復(fù)制、哨兵、Cluster三種模式詳細(xì)介紹
文章路徑:http://muchs.cn/article0/pdggio.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站策劃網(wǎng)站導(dǎo)航、微信小程序、App設(shè)計(jì)、微信公眾號(hào)、定制網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)