三千字介紹Redis主從+哨兵+集群
一、Redis持久化策略
1.RDB
每隔幾分鐘或者一段時(shí)間會(huì)將redis內(nèi)存中的數(shù)據(jù)全量的寫入到一個(gè)文件中去。
優(yōu)點(diǎn):
因?yàn)樗敲扛粢欢螘r(shí)間的全量備份,代表了每個(gè)時(shí)間段的數(shù)據(jù)。所以適合做冷備份。
RDB對(duì)redis的讀寫影響非常小,因?yàn)閞edis主進(jìn)程只需要fork一個(gè)子進(jìn)程進(jìn)行磁盤IO操作就行了。
相對(duì)于AOF來說,恢復(fù)較快,因?yàn)橐粋€(gè)RDB就是數(shù)據(jù)文件,而AOF存的是指令日志。
缺點(diǎn):
因?yàn)槭且欢螘r(shí)間才備份,所以容易丟數(shù)據(jù)。
如果一次寫入的文件大,會(huì)導(dǎo)致讀寫服務(wù)暫停幾毫秒,甚至幾秒。
2.AOF
會(huì)將每條寫入指令都寫入到linux os緩存中去,然后每秒鐘會(huì)將linux os中的指令作為日志追加到AOF的文件里面。
當(dāng)redis內(nèi)存大小達(dá)到一定的量,會(huì)通過LRU(最近最少使用)淘汰機(jī)制淘汰掉數(shù)據(jù),然后再重寫一個(gè)新的AOF文件出來。這樣也保證了AOF文件不會(huì)無限制的增大。
優(yōu)點(diǎn):
不易丟數(shù)據(jù)
AOF日志文件是以append-only的模式寫入,沒有磁盤尋址的開銷,寫入性能高,文件也不易破損
AOF文件過大的時(shí)候,后臺(tái)重寫操作,也不會(huì)影響客戶端。再rewrite的時(shí)候,會(huì)對(duì)指令壓縮,創(chuàng)建出一份需要恢復(fù)的最小日志出來,再創(chuàng)建新日志文件時(shí),老的文件照常寫入,當(dāng)新文件準(zhǔn)備好了,再交換新老日志文件就行了
日志文件的命令是可讀的,可以作為誤刪的緊急恢復(fù)。停了服務(wù),再把那條刪除指令刪除,再恢復(fù)就行了。
缺點(diǎn):
AOF日志文件占用的磁盤空間比較大
開啟AOF后,寫操作的QPS會(huì)下降
以前出過bug,恢復(fù)的數(shù)據(jù)和原來不一樣,健壯性沒有RDB高
恢復(fù)數(shù)據(jù)慢,且不適合做冷備(需要手動(dòng)寫腳本)
3.混合持久化(Redis 4.0)
開啟混合持久化
aof-use-rdb-preamble yes
綜合來說:
我們可以采用兩種都用的的方案,RDB做冷備,為了保證數(shù)據(jù)不丟失,AOF做數(shù)據(jù)恢復(fù)的第一選擇。
如何配置持久化?
找到/usr/local/package/redis-4.0.9/redis.conf
RDB的配置
?//每隔60秒,如果有10000個(gè)key發(fā)生改變就持久化一次
????save?60?10000
AOF的配置
????#?redis默認(rèn)關(guān)閉AOF機(jī)制,可以將no改成yes實(shí)現(xiàn)AOF持久化
????appendonly?no
????#?AOF文件
????appendfilename?"appendonly.aof"
????# AOF持久化同步頻率,always表示每個(gè)Redis寫命令都要同步fsync寫入到磁盤中,但是這種方式會(huì)嚴(yán)重降低redis的速度;everysec表示每秒執(zhí)行一次同步fsync,顯示的將多個(gè)寫命令同步到磁盤中;no表示讓操作系統(tǒng)來決定應(yīng)該何時(shí)進(jìn)行同步fsync,Linux系統(tǒng)往往可能30秒才會(huì)執(zhí)行一次
????#?appendfsync?always
????appendfsync?everysec
????#?appendfsync?no
????
????#?在日志進(jìn)行BGREWRITEAOF時(shí),如果設(shè)置為yes表示新寫操作不進(jìn)行同步fsync,只是暫存在緩沖區(qū)里,避免造成磁盤IO操作沖突,等重寫完成后在寫入。redis中默認(rèn)為no ?
????no-appendfsync-on-rewrite?no???
????#?當(dāng)前AOF文件大小是上次日志重寫時(shí)的AOF文件大小兩倍時(shí),發(fā)生BGREWRITEAOF操作。??
????auto-aof-rewrite-percentage?100??
????#當(dāng)前AOF文件執(zhí)行BGREWRITEAOF命令的最小值,避免剛開始啟動(dòng)Reids時(shí)由于文件尺寸較小導(dǎo)致頻繁的BGREWRITEAOF。??
????auto-aof-rewrite-min-size?64mb??
????#?Redis再恢復(fù)時(shí),忽略最后一條可能存在問題的指令(因?yàn)樽詈笠粭l指令可能存在問題,比如寫一半時(shí)突然斷電了)
????aof-load-truncated?yes
????#Redis4.0新增RDB-AOF混合持久化格式,在開啟了這個(gè)功能之后,AOF重寫產(chǎn)生的文件將同時(shí)包含RDB格式的內(nèi)容和AOF格式的內(nèi)容,其中RDB格式的內(nèi)容用于記錄已有的數(shù)據(jù),而AOF格式的內(nèi)存則用于記錄最近發(fā)生了變化的數(shù)據(jù),這樣Redis就可以同時(shí)兼有RDB持久化和AOF持久化的優(yōu)點(diǎn)(既能夠快速地生成重寫文件,也能夠在出現(xiàn)問題時(shí),快速地載入數(shù)據(jù))。
????aof-use-rdb-preamble?no
AOF rewrite過程
redis fork一個(gè)子進(jìn)程
子進(jìn)程基于當(dāng)前內(nèi)存中的數(shù)據(jù)開始寫入一個(gè)新的aof的文件
這時(shí)新的命令進(jìn)來,會(huì)存在內(nèi)存中,也會(huì)存在舊的aof文件中
當(dāng)新的aof文件寫好了,這個(gè)過程中的新的命令也會(huì)追加到aof里來
然后用新日志文件替換掉舊的日志文件
注意:當(dāng)使用shutdown命令關(guān)閉redis服務(wù)時(shí),會(huì)自動(dòng)備份一個(gè)快照
。
當(dāng)RDB生成快照時(shí),AOF不會(huì)rewrite。反之亦然。
redis如果遇到斷電或機(jī)器故障問題時(shí)怎么辦?
答:一般使用持久化加服務(wù)器文件(將文件備份到阿里云)備份的方案
二、Redis淘汰策略
LRU:(least recently used)最近最少使用
標(biāo)準(zhǔn)的LRU算法:
使用HashMap+雙向鏈表
核心步驟:
save操作時(shí),在hashmap中找對(duì)應(yīng)的key值,如果存在,更新他并移到隊(duì)頭,如果不存在,則構(gòu)建新節(jié)點(diǎn),并移到隊(duì)頭,如果隊(duì)列滿了,則移除隊(duì)尾的節(jié)點(diǎn),并在hashmap中移除該key
get操作時(shí),在hashmap中找到對(duì)應(yīng)的節(jié)點(diǎn),將他移到隊(duì)頭
redis里面沒有使用雙向鏈表的實(shí)現(xiàn)方式,而是使用了一個(gè)pool池.
Redis的LRU實(shí)現(xiàn)
常用策略:allkeys-lru
Redis使用的是近似LRU算法
給每個(gè) key 增加一個(gè)額外 24bit 長度的小字段, 存儲(chǔ)該 key 的最后一次訪問時(shí)間戳
當(dāng)空間滿時(shí), 隨機(jī)采樣取出 5 個(gè) key (數(shù)量可配置), 按時(shí)間戳淘汰掉最舊的 key
循環(huán)第二步, 直到內(nèi)存低于 maxmemory 值
隨機(jī)采樣的范圍取決于配置的策略是 volatile 還是 allkeys
Redis 3.0 開始, 增加了淘汰池進(jìn)一步提升了近似 LRU 的效果:
上一次隨機(jī)采樣后未淘汰的 key, 會(huì)放入 淘汰池 留待下一次循環(huán),
下一次隨機(jī)采樣的key會(huì)先和淘汰池中的key合并后, 再計(jì)算淘汰最舊的key
三、Redis主從架構(gòu)
1.主從特性
采用異步的方式復(fù)制到slave節(jié)點(diǎn),不過redis2.8之后,每個(gè)slave節(jié)點(diǎn)會(huì)周期性的確認(rèn)自己每次復(fù)制的數(shù)據(jù)量
一個(gè)master可以配置多個(gè)slave
slave node也可以連接其他的slave node
slave復(fù)制時(shí)不影響master的工作
slave復(fù)制時(shí)也不會(huì)影響slave的查詢操作,他會(huì)用舊的數(shù)據(jù)提供服務(wù)。但是當(dāng)復(fù)制完成,需要?jiǎng)h除舊數(shù)據(jù),加載新數(shù)據(jù)集時(shí),會(huì)暫停服務(wù)。
slave主要用來做橫向擴(kuò)容,做讀寫分離
2.主從復(fù)制步驟
當(dāng)slave第一次連接時(shí),master會(huì)生成一個(gè)全量RDB文件給他做恢復(fù),并將這個(gè)過程中新的寫入命令緩存在內(nèi)存中,等slave把RDB文件讀入之后發(fā)給他
當(dāng)slave斷開一段時(shí)間后重連,master會(huì)將缺失的數(shù)據(jù)發(fā)給他
平時(shí)情況下,master收到一個(gè)指令,都會(huì)馬上復(fù)制給slave
3.斷點(diǎn)續(xù)傳
從redis2.8開始,就支持主從復(fù)制的斷點(diǎn)續(xù)傳
master中存了backlog,master和slave都會(huì)保存一個(gè)replica offset,還有一個(gè)master id。如果中途網(wǎng)絡(luò)斷了,slave會(huì)讓master從上次的replica offset開始繼續(xù)復(fù)制。
4.過期key處理
slave不會(huì)過期key,只會(huì)等master過期key之后或者根據(jù),模LRU淘汰了key之后擬一個(gè)del命令發(fā)給slave
5.配置主從服務(wù)器
安裝redis
cp utils/redis_init_script /etc/init.d/redis_6379
redis自啟動(dòng) chkconfig redis_6379 on
mkdir /etc/redis
mkdir -p /var/redis/6379
cp redis.conf /etc/redis/6379.conf
修改配置文件6379.conf
daemonize yes //讓redis以daemon進(jìn)程運(yùn)行
dir /var/redis/6379
slaveof CentOS01 6379
slave 服務(wù)器的配置文件上配 masterauth 123456
master服務(wù)器的配置文件上配
requirepass 123456每個(gè)6379.conf里都要將bind 127.0.0.1改成bind 自己本機(jī)的ip
讓redis跟隨系統(tǒng)啟動(dòng)自動(dòng)啟動(dòng)
在redis_6379腳本中,最上面,加入兩行注釋
#chkconfig:???2345?90?10??
#description:??Redis?is?a?persistent?key-value?database
然后執(zhí)行
chkconfig redis_6379 on
8. 壓測(cè)性能 ./redis-benchmark -c 50 -n 10000
復(fù)制原理圖:
注意:主從架構(gòu)建議必須開啟master節(jié)點(diǎn)的持久化。
四、哨兵模式
1.概念介紹
介紹:
集群監(jiān)控,監(jiān)控master和slave是否正常
消息通知,如果某個(gè)redis實(shí)例故障了,負(fù)責(zé)發(fā)消息給管理員
故障轉(zhuǎn)移,如果master節(jié)點(diǎn)掛掉了,會(huì)自動(dòng)轉(zhuǎn)移到slave上
配置中心,如果故障轉(zhuǎn)移發(fā)生了,通知client新的master地址
2.故障轉(zhuǎn)移
哨兵至少要3個(gè)實(shí)例
如圖:
如果只有2個(gè)哨兵會(huì)如何呢?
master宕機(jī),s1和s2中只要有1個(gè)哨兵認(rèn)為master宕機(jī)就可以進(jìn)行切換,同時(shí)s1和s2中會(huì)選舉出一個(gè)哨兵來執(zhí)行故障轉(zhuǎn)移
同時(shí)這個(gè)時(shí)候,需要majority,也就是大多數(shù)哨兵都是運(yùn)行的,2個(gè)哨兵的majority就是2(2的majority=2,3的majority=2,5的majority=3,4的majority=2),2個(gè)哨兵都運(yùn)行著,就可以允許執(zhí)行故障轉(zhuǎn)移
但是如果整個(gè)M1和S1運(yùn)行的機(jī)器宕機(jī)了,那么哨兵只有1個(gè)了,此時(shí)就沒有majority來允許執(zhí)行故障轉(zhuǎn)移,雖然另外一臺(tái)機(jī)器還有一個(gè)R1,但是故障轉(zhuǎn)移不會(huì)執(zhí)行
3.解決異步復(fù)制和腦裂導(dǎo)致的數(shù)據(jù)丟失
min-slaves-to-write 1
min-slaves-max-lag 10
要求至少有1個(gè)slave,數(shù)據(jù)復(fù)制和同步的延遲不能超過10秒
4.sdown和odown轉(zhuǎn)換機(jī)制
sdown:主觀宕機(jī),即一個(gè)哨兵覺得master宕機(jī)了
odown:客觀宕機(jī),即quorum數(shù)量的哨兵覺得master宕機(jī)了
5.哨兵集群的自動(dòng)發(fā)現(xiàn)機(jī)制
哨兵互相之間的發(fā)現(xiàn),是通過redis的pub/sub系統(tǒng)實(shí)現(xiàn)的,每個(gè)哨兵都會(huì)往__sentinel__:hello這個(gè)channel里發(fā)送一個(gè)消息,這時(shí)候所有其他哨兵都可以消費(fèi)到這個(gè)消息,并感知到其他的哨兵的存在
每隔兩秒鐘,每個(gè)哨兵都會(huì)往自己監(jiān)控的某個(gè)master+slaves對(duì)應(yīng)的__sentinel__:hello channel里發(fā)送一個(gè)消息,內(nèi)容是自己的host、ip和runid還有對(duì)這個(gè)master的監(jiān)控配置
每個(gè)哨兵也會(huì)去監(jiān)聽自己監(jiān)控的每個(gè)master+slaves對(duì)應(yīng)的__sentinel__:hello channel,然后去感知到同樣在監(jiān)聽這個(gè)master+slaves的其他哨兵的存在
每個(gè)哨兵還會(huì)跟其他哨兵交換對(duì)master的監(jiān)控配置,互相進(jìn)行監(jiān)控配置的同步
6.選舉算法
如果一個(gè)master被認(rèn)為odown了,而且majority哨兵都允許了主備切換,那么某個(gè)哨兵就會(huì)執(zhí)行主備切換操作,此時(shí)首先要選舉一個(gè)slave來
會(huì)考慮slave的一些信息
(1)跟master斷開連接的時(shí)長
(2)slave優(yōu)先級(jí)
(3)復(fù)制offset
(4)run id
7.部署哨兵
復(fù)制配置文件
????mkdir?-p?/var/sentinel/5000
????mkdir?/etc/sentinel
????mkdir?-p?/var/log/sentinal/5000
????mv?/usr/local/package/redis-4.0.9/sentinel.conf?/etc/sentinel/5000.conf
修改配置文件
??port?5000
??bind??192.168.1.14
??sentinel?monitor?mymaster?192.168.1.12?6379?2
??dir?/var/sentinel/5000
??sentinel?parallel-syncs?mymaster?1
??sentinel?failover-timeout?mymaster?60000
??sentinel?down-after-milliseconds?mymaster?30000
??sentinel?auth-pass?mymaster?123456
??daemonize?yes
??logfile?/var/log/sentinal/5000/sentinel.log
注意:sentinel monitor mymaster 192.168.1.12 6379 2 這行要放在使用mymaster的那些其他配置之前
啟動(dòng)哨兵
./redis-sentinel /etc/sentinel/5000.conf
五、redis集群
1.概念介紹
自動(dòng)對(duì)數(shù)據(jù)進(jìn)行分片,每個(gè)master上存放一部分?jǐn)?shù)據(jù)
提供內(nèi)置的高可用支持,部分master不可用了,還是可以繼續(xù)工作的
2.部署選型
redis cluster VS replication + sentinel
當(dāng)數(shù)據(jù)量少,主要承載的是高并發(fā)時(shí),單機(jī)就足夠了。一個(gè)master多個(gè)slave,在搭建一個(gè)sentinel集群來保證高可用性
redis cluster主要還是用來做海量數(shù)據(jù)的緩存。
3.分布式Hash算法
當(dāng)需要把數(shù)據(jù)分到不同的幾個(gè)機(jī)器存儲(chǔ)時(shí),就需要一個(gè)算法了。
方法一:取模
對(duì)數(shù)據(jù)的hash值取模,比如有3臺(tái)集器,那么就用hash%3,得到的就是0-2的三個(gè)數(shù)字,就可以確定將數(shù)據(jù)存在哪一臺(tái)上面了
缺點(diǎn):如果有一臺(tái)機(jī)器掛掉了,那么數(shù)據(jù)會(huì)對(duì)2取模,那么得到的機(jī)器號(hào)就錯(cuò)亂了,導(dǎo)致大量數(shù)據(jù)不能從正確的機(jī)器上去取
方法二:一致性hash算法(圓環(huán)算法)
將3臺(tái)機(jī)器放在一個(gè)圓環(huán)上,然后要緩存的數(shù)據(jù)經(jīng)過計(jì)算也落在圓環(huán)的某一個(gè)點(diǎn),然后順時(shí)針去環(huán)上找離他最近的那個(gè)機(jī)器。
優(yōu)點(diǎn):當(dāng)一臺(tái)機(jī)器掛掉,不影響其他的機(jī)器上存的數(shù)據(jù)
缺點(diǎn):具有熱點(diǎn)問題,可能某一個(gè)機(jī)器會(huì)有大量數(shù)據(jù),這就需要將每個(gè)機(jī)器都多設(shè)置幾個(gè)虛擬節(jié)點(diǎn),均勻分布在圓環(huán)上。

方法三:redis cluster的hash slot算法
redis cluster有固定的16384個(gè)slot,對(duì)每個(gè)key計(jì)算CRC16值,然后對(duì)16384取模,獲取對(duì)應(yīng)的slot,每個(gè)master都有部分的slot。這樣的話如果增加一個(gè)master,就將其他master上的slot分點(diǎn)給她就行了。
4.部署redis集群
創(chuàng)建目錄
??mkdir?-p?/etc/redis-cluster
??mkdir?-p?/var/log/redis
??mkdir?/var/redis/7001
??mkdir?/var/redis/7002
修改配置文件 7001.conf
??port?7001
??cluster-enabled?yes
??cluster-config-file?/etc/redis-cluster/node-7001.conf
??cluster-node-timeout?15000
??pidfile?"/var/run/redis_7001.pid"
??dir?"/var/redis/7001"
??logfile?"/var/log/redis/7001.log"
修改配置文件
vi?/usr/local/share/gems/gems/redis-3.2.1/lib/redis/client.rb
password=123456
執(zhí)行
?echo?never?>?/sys/kernel/mm/transparent_hugepage/enabled
啟動(dòng)腳本
???cd?/etc/init.d/
???cp?redis_6379?redis_7001
修改redis_7001配置
??REDISPORT=7001
安裝ruby
???yum?install?-y?ruby
????下載一個(gè)redis-3.2.1.gem,然后執(zhí)行
????gem?install?redis
????
????cp?/usr/local/package/redis-4.0.9/src/redis-trib.rb?/usr/local/bin
????
????/usr/local/bin/redis-trib.rb?create?--replicas?1?192.168.1.12:7001?192.168.1.12:7002?192.168.1.13:7003?192.168.1.13:7004?192.168.1.14:7005?192.168.1.14:7006
檢查節(jié)點(diǎn)狀態(tài)
?./redis-trib.rb?check?192.168.1.12?7001
? 作者?|??女友在高考
來源 |??cnblogs.com/javammc/p/15358177.html

