目錄
1、Redis持久化
- 優(yōu)缺點(diǎn)對(duì)比
- 實(shí)際配置
- 根據(jù)RDB文件的恢復(fù)過(guò)程
2、Redis讀寫(xiě)分離架構(gòu)
- 注意事項(xiàng)
- 復(fù)制流程
- 數(shù)據(jù)丟失場(chǎng)景
- 哨兵
3、Redis集群架構(gòu)
- 數(shù)據(jù)的負(fù)載均衡算法
- 實(shí)際操作
- 主備切換過(guò)程
4、緩存架構(gòu)
- 一般緩存架構(gòu)
- 多級(jí)緩存架構(gòu)
5、數(shù)據(jù)清除策略
- 配置
- 流程
Redis持久化
持久化策略共提供了兩種
RDB 全量備份
每隔一個(gè)時(shí)間間隔做Redis的一份快照,記錄當(dāng)前Redis中的全都數(shù)據(jù)AOF 增量備份
記錄Redis的每一次操作到AOF文件
AOF流程:
Redis只有一個(gè)AOF文件,在Redis和AOF文件間存在一個(gè)OSCache系統(tǒng)級(jí)緩存,Redis每次寫(xiě)操作先存儲(chǔ)在OSCache中,每隔一段時(shí)間執(zhí)行fsync操作,將OSCache中的數(shù)據(jù)再寫(xiě)入磁盤(pán)中的AOF文件,這時(shí)才真正的存儲(chǔ)在磁盤(pán)上。
Redis的內(nèi)存是一定量的,AOF則是記錄每條數(shù)據(jù)的操作,所以會(huì)逐漸變大。當(dāng)Redis執(zhí)行LRU策略淘汰某些數(shù)據(jù)時(shí),AOF中記錄的數(shù)據(jù)就會(huì)過(guò)期,所以當(dāng)AOF到一定程度時(shí)會(huì)有rewrite操作。rewrite操作會(huì)根據(jù)當(dāng)前Redis中的數(shù)據(jù),重新構(gòu)建一個(gè)新AOF文件,以清除過(guò)期失效的記錄縮小AOF文件大小,構(gòu)建完成后替換舊的AOF文件。
優(yōu)缺點(diǎn)對(duì)比
RDB優(yōu)點(diǎn):適合冷備、性能高(不必一條條記錄寫(xiě)磁盤(pán))、數(shù)據(jù)恢復(fù)快
RDB缺點(diǎn):丟數(shù)據(jù)多(時(shí)間間隔內(nèi)的數(shù)據(jù))、數(shù)據(jù)量多時(shí)恢復(fù)會(huì)有延遲
AOF優(yōu)點(diǎn):最多丟時(shí)間間隔內(nèi)的數(shù)據(jù)(間隔比RDB短)、append-only模式不需尋址寫(xiě)入AOF文件性能高,文件不易破損
AOF缺點(diǎn):相同情況下AOF文件大于RDB文件大小、拖慢Redis的QPS、數(shù)據(jù)恢復(fù)慢(重放操作)
實(shí)際配置
RDB
redis.conf文件,SNAPSHOTTING節(jié)點(diǎn)下設(shè)置RDB的相關(guān)參數(shù)
默認(rèn)設(shè)置
save 900 1
save 300 10
save 60 1000
即:每隔60秒超過(guò)1000個(gè)key發(fā)生變更,則生成一個(gè)dump.rdb文件
配置文件內(nèi)可配置多個(gè)檢查點(diǎn)
生成的dump.rdb文件在配置的dir目錄下,新文件覆蓋舊文件
安全退出Redis,會(huì)自動(dòng)觸發(fā)生成當(dāng)前Redis的dump.rdb文件
AOF
redis.conf文件,APPEND ONLY MODE節(jié)點(diǎn)下設(shè)置AOF的相關(guān)參數(shù)
RDB是默認(rèn)打開(kāi)的,而AOF是默認(rèn)關(guān)閉
appendonly yes 打開(kāi)AOF
若Redis重啟且AOF和RDB都開(kāi)啟的情況下,優(yōu)先AOF恢復(fù)(數(shù)據(jù)完整性較RDB好)在dir目錄下查找AOF文件進(jìn)行恢復(fù)
fsync操作的設(shè)置,會(huì)影響數(shù)據(jù)的丟失量
appendfsync always 每寫(xiě)入一條數(shù)據(jù),立即執(zhí)行fsync操作將數(shù)據(jù)寫(xiě)入磁盤(pán),性能差、吞吐量低
appendfsync everysec 每秒將OSCache中的數(shù)據(jù)刷入磁盤(pán),QPS在萬(wàn)級(jí)別,默認(rèn)項(xiàng)
appendfsync no 數(shù)據(jù)進(jìn)入OSCache后,由OS決定刷入磁盤(pán)的時(shí)機(jī)
rewrite策略,控制AOF文件不至于無(wú)限增長(zhǎng)
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
較上次rewrite的AOF文件大小,增長(zhǎng)比例達(dá)到100%,且AOF文件大于min-size大小,則觸發(fā)rewrite操作
rewrite流程:
- Redis fork一個(gè)子進(jìn)程,基于當(dāng)前內(nèi)存的數(shù)據(jù)構(gòu)建日志,寫(xiě)入新AOF文件中。
- 此時(shí)Redis主進(jìn)程能繼續(xù)接收外部的寫(xiě)操作,并將操作記錄存入一塊內(nèi)存同時(shí)寫(xiě)入舊AOF文件中。
- 子進(jìn)程完成后,主進(jìn)程將內(nèi)存中新記錄追加到新AOF文件中
- 新AOF文件替換舊AOF文件
AOF 文件修復(fù)
因?yàn)锳OF文件采用append-only模式寫(xiě)入,所以文件破損只會(huì)發(fā)生在文件尾部
redis-check-aof --fix [file] 通過(guò)此命令進(jìn)行AOF的文件修復(fù)
RDB全量備份與AOF的rewrite不會(huì)同時(shí)進(jìn)行,若發(fā)生則等待前一操作完成后執(zhí)行(磁盤(pán)IO開(kāi)銷(xiāo)太大)
根據(jù)RDB文件的恢復(fù)過(guò)程
1.關(guān)閉AOF配置項(xiàng),否則默認(rèn)根據(jù)AOF恢復(fù),如沒(méi)有發(fā)現(xiàn)AOF文件則會(huì)生成一份空的AOF文件,并根據(jù)空的AOF文件恢復(fù)
2.拷貝RDB文件到目錄,重啟Redis,完成恢復(fù)
3.熱修改開(kāi)啟AOF,這時(shí)生成的AOF文件會(huì)存儲(chǔ)當(dāng)前數(shù)據(jù),但通過(guò)熱修改配置的方式在配置文件內(nèi)并沒(méi)有實(shí)際修改
4.關(guān)閉Redis,手動(dòng)修改配置開(kāi)啟AOF,再次重啟Redis
Redis讀寫(xiě)分離架構(gòu)
Redis緩存主要應(yīng)對(duì)的是讀請(qǐng)求場(chǎng)景,對(duì)于未命中項(xiàng)則會(huì)請(qǐng)求到數(shù)據(jù)庫(kù),MySQL正常的QPS在1~2K。要想達(dá)到高并發(fā),需要將讀請(qǐng)求在Redis緩存層處理掉。
單機(jī)Redis可承載萬(wàn)級(jí)的QPS(視業(yè)務(wù)場(chǎng)景、機(jī)器而定),要承載更高的并發(fā)需要進(jìn)行讀寫(xiě)分離,master node只負(fù)責(zé)寫(xiě)操作,slave node負(fù)責(zé)讀操作,兩者數(shù)據(jù)一致。當(dāng)并發(fā)量增加時(shí),可橫向擴(kuò)展增加slave node來(lái)分?jǐn)俀PS。

注意事項(xiàng)
master node采用異步的方式復(fù)制數(shù)據(jù)到slave node,不會(huì)影響master node的正常操作
slave node復(fù)制數(shù)據(jù)期間會(huì)提供對(duì)外的讀操作,只不過(guò)數(shù)據(jù)復(fù)制完成前提供的數(shù)據(jù)是舊數(shù)據(jù)。復(fù)制完成后,刪除舊數(shù)據(jù)加載新數(shù)據(jù)階段,會(huì)暫停對(duì)外的服務(wù)。
采用主從架構(gòu)需要對(duì)master node做持久化,否則master node故障重啟后(偵測(cè)機(jī)制還未觸發(fā))數(shù)據(jù)丟失,將會(huì)影響所有的slave node
slave node不會(huì)過(guò)期key,master node過(guò)期key后會(huì)del通知給slave node
master node和slave node之間通過(guò)心跳相互聯(lián)系
一個(gè)master node可以配置多個(gè)slave node,slave node之間也可以互相連接
復(fù)制流程
slave node啟動(dòng)時(shí),讀取conf配置slaveof中master node的IP和port,slave node內(nèi)部的定時(shí)任務(wù),定期檢查是否有新的master node需要連接和復(fù)制,并進(jìn)行socket連接
slave node發(fā)送ping命令給master node,若master node設(shè)置了requirepass,則slave node必須發(fā)送masterauth口令進(jìn)行認(rèn)證
如果是第一次連接會(huì)觸發(fā)full resynchronization,master node采用異步的方式復(fù)制數(shù)據(jù)到slave node;如果是重連,master node僅會(huì)復(fù)制slave node缺少的數(shù)據(jù)。
開(kāi)始full resynchronization時(shí),master node會(huì)用后臺(tái)線程做一份RDB的快照文件,slave node會(huì)將RDB文件寫(xiě)入自己的磁盤(pán)后再加載到內(nèi)存。期間master node的寫(xiě)操作會(huì)記錄在內(nèi)存,master node會(huì)將內(nèi)存中的寫(xiě)命令發(fā)送給slave node
master node和slave node都會(huì)維護(hù)一個(gè)offset,且在不斷累加,記錄當(dāng)前的數(shù)據(jù)。slave node會(huì)定期上報(bào)master node自己的offset,master node也會(huì)記錄各個(gè)slave node的offset,用來(lái)知曉相互間的數(shù)據(jù)差異。
若在復(fù)制的過(guò)程中連接斷開(kāi)重連,slave node可以從offset的位置繼續(xù)復(fù)制,如果找不到對(duì)應(yīng)的offset則會(huì)執(zhí)行resynchronization;slave node也會(huì)記錄master run id,若發(fā)現(xiàn)master run id不同,可能是master node重啟或發(fā)生變化,需要做全量復(fù)制
配置文件redis.conf中可以設(shè)置生成的RDB文件是否落在本地磁盤(pán)
repl-diskless-sync no 是否開(kāi)啟無(wú)磁盤(pán)化復(fù)制
repl-diskless-sync-delay [] 延遲復(fù)制,等待更多的slave node連接
參數(shù)配置
slaveof [ip] [port] 填入master node的信息
slave-read-only yes 默認(rèn)開(kāi)啟slave node只讀
數(shù)據(jù)丟失場(chǎng)景


解決方法
min-slaves-to-write 1 最少要寫(xiě)入slave node的數(shù)量為1
min-slaves-max-lag 10 master node和slave node間數(shù)據(jù)延遲不能超過(guò)10秒
此配置默認(rèn)未開(kāi)啟
此配置只是降低數(shù)據(jù)損失量,剩余要client做降級(jí)操作減少損失
哨兵
哨兵是分布式的架構(gòu),最少有3個(gè)實(shí)例,以保證自己的健壯性。
哨兵只保證Redis的高可用,不保證數(shù)據(jù)的零丟失
哨兵間的通訊通過(guò)Redis的pub/sub系統(tǒng)實(shí)現(xiàn)
功能
- 集群監(jiān)控 監(jiān)控Redis中master node和slave node是否正常工作
- 消息通知 Redis實(shí)例故障時(shí)發(fā)送通知
- 故障轉(zhuǎn)移 如果master node故障,會(huì)選舉新master node
- 配置中心 故障轉(zhuǎn)移時(shí)會(huì)將新配置項(xiàng)通知各個(gè)端
工作流程
哨兵有兩種失敗狀態(tài),1個(gè)哨兵認(rèn)為master node掛了就是sdown(主觀宕機(jī)),quorum數(shù)量個(gè)哨兵認(rèn)為master node掛了就是odown(客觀宕機(jī))。
當(dāng)哨兵ping master node響應(yīng)時(shí)間超過(guò)設(shè)置的down-after-milliseconds時(shí)進(jìn)入sdown狀態(tài)
如果master node被認(rèn)為odown,且有majority數(shù)量的哨兵允許主備切換,就會(huì)有一個(gè)哨兵執(zhí)行主備切換的操作,選舉一個(gè)slave node作為新master node
考慮因素包括:與master node斷開(kāi)的時(shí)長(zhǎng)、slave node的優(yōu)先級(jí)、offset值、run id值
配置參數(shù)
sentinel.conf
哨兵可以監(jiān)控多個(gè)Redis的主從架構(gòu)
sentinel monitor [架構(gòu)名] [ip] [quorum] 監(jiān)控的主從架構(gòu)信息
sentinel down-after-milliseconds [架構(gòu)名] 60000 超過(guò)設(shè)置時(shí)間認(rèn)為sdown
sentinel failover-timeout [架構(gòu)名] 180000 執(zhí)行故障轉(zhuǎn)移的超時(shí)時(shí)間
sentinel parallel-sync [架構(gòu)名] 1 并行同步數(shù),新選舉的master node,每次同步slave node的數(shù)據(jù)量,數(shù)據(jù)同步完成后才會(huì)執(zhí)行后面slave node的同步
port [] 端口號(hào)
bind [ip] 綁定本機(jī)IP
daemonize yes 后臺(tái)執(zhí)行
logfile /var/log/sentinel/*.log 設(shè)置日志文件
Redis集群架構(gòu)
讀寫(xiě)分離架構(gòu):master node負(fù)責(zé)寫(xiě)操作,slave node負(fù)責(zé)讀操作,配合哨兵能夠達(dá)到高可用。
集群架構(gòu):存在多個(gè)master node,每個(gè)master node上可掛載多個(gè)slave node。各個(gè)master node之間數(shù)據(jù)不同,能夠提供讀寫(xiě)操作。當(dāng)master node掛掉后,slave node頂上以達(dá)到高可用。
讀寫(xiě)分離的架構(gòu)能夠存儲(chǔ)的數(shù)據(jù)量?jī)H為master node的內(nèi)存容量,在海量數(shù)據(jù)場(chǎng)景下會(huì)產(chǎn)生瓶頸,因此在海量數(shù)據(jù)場(chǎng)景下適用集群架構(gòu)

數(shù)據(jù)的負(fù)載均衡算法
Hash算法(散列算法)用一種較短的信息來(lái)保證內(nèi)容唯一性的算法。在Redis集群架構(gòu)下如果某一節(jié)點(diǎn)掛了,則會(huì)導(dǎo)致全部信息失效。
一致性Hash算法,節(jié)點(diǎn)之間采用環(huán)形,在Redis集群架構(gòu)下如果某一節(jié)點(diǎn)掛了,則只會(huì)丟失此節(jié)點(diǎn)數(shù)據(jù)。熱點(diǎn)問(wèn)題采用虛擬節(jié)點(diǎn)來(lái)負(fù)載均衡
Hash slot算法,數(shù)據(jù)存儲(chǔ)在slot上,slot存儲(chǔ)在節(jié)點(diǎn)上,如果某一節(jié)點(diǎn)掛了,數(shù)據(jù)是尋找slot而不是節(jié)點(diǎn),且掛掉的節(jié)點(diǎn)會(huì)將本節(jié)點(diǎn)上的slot遷移到其他節(jié)點(diǎn)。
實(shí)際操作
配置參數(shù)
cluster-enabled yes 啟動(dòng)集群架構(gòu),不可同時(shí)開(kāi)啟讀寫(xiě)分離架構(gòu)
cluster-config-file [配置文件] 指定配置文件
cluster-node-timeout [] 節(jié)點(diǎn)超時(shí)時(shí)長(zhǎng),超時(shí)則主備切換
port []
daemonize yes
pidfile /var/run/redis_[port].pid
dir /var/redis/[port]
logfile /var/log/redis/[port].log
bind [ip]
appendonly yes
集群操作
redis-trib.rb create --replicas [slave node數(shù)量] [ip:port] [ip:port] [ip:port] [ip:port]... 啟動(dòng)cluster
redis-trib.rb add-node [ip:port]... 擴(kuò)容master
redis-trib.rb reshard [ip:port] 會(huì)有交互提示輸入數(shù)據(jù)遷移的參數(shù)
redis-trib.rb add-node --slave --master-id [id] [ip:port] 給master節(jié)點(diǎn)增加slave
redis-trib.rb del-node [ip:port] [id] 刪除節(jié)點(diǎn)
master node不存在slot時(shí),cluster會(huì)將其slave node掛到其他master node上
cluster會(huì)將冗余的slave node分配給其他master node,以保證高可用
主備切換過(guò)程
各個(gè)節(jié)點(diǎn)保存集群元數(shù)據(jù),節(jié)點(diǎn)間采用gossip協(xié)議進(jìn)行通訊,通過(guò)節(jié)點(diǎn)間不斷的通訊以保持整個(gè)集群的數(shù)據(jù)完整性
當(dāng)一個(gè)節(jié)點(diǎn)認(rèn)為另一個(gè)節(jié)點(diǎn)宕機(jī)了(響應(yīng)時(shí)間超過(guò)cluster-node-timeout)稱(chēng)為pfail(主觀宕機(jī)),多個(gè)節(jié)點(diǎn)認(rèn)為一個(gè)節(jié)點(diǎn)宕機(jī)了稱(chēng)為fail(客觀宕機(jī))
對(duì)于宕機(jī)的master node,從其slave node中選取一個(gè)切換為master node
篩選的條件和哨兵類(lèi)似:斷開(kāi)連接時(shí)間(時(shí)間超過(guò)cluster-node-timeout*cluster-slave-validity-factory的slave node沒(méi)有資格參見(jiàn)選舉)、priority、offset、run id
緩存架構(gòu)
一般緩存架構(gòu)

1.用戶(hù)發(fā)起請(qǐng)求
2.讀請(qǐng)求發(fā)起后被web服務(wù)器轉(zhuǎn)發(fā)到web服務(wù)上
3.web服務(wù)先向Redis緩存查詢(xún)
4.數(shù)據(jù)命中則將數(shù)據(jù)返回給用戶(hù)
5.未命中則去數(shù)據(jù)庫(kù)查詢(xún)數(shù)據(jù)
6.數(shù)據(jù)命中后返回給web服務(wù)
7.web服務(wù)接收到數(shù)據(jù)后將數(shù)據(jù)返回給用戶(hù),同時(shí)緩存數(shù)據(jù)
多級(jí)緩存架構(gòu)

緩存操作
- 同步緩存操作
1.用戶(hù)向XX服務(wù)發(fā)送寫(xiě)請(qǐng)求
2.XX服務(wù)將數(shù)據(jù)同步更新到DB和Redis緩存
- 異步緩存操作
1.用戶(hù)向XX服務(wù)發(fā)送寫(xiě)請(qǐng)求
2.XX服務(wù)將數(shù)據(jù)更新到DB同時(shí)向MQ發(fā)送消息
3.web服務(wù)接收到消息后,將數(shù)據(jù)寫(xiě)到本地緩存和Redis緩存中
讀取操作
1.用戶(hù)向web服務(wù)器發(fā)送讀請(qǐng)求
2.在web服務(wù)器緩存中命中則返回,否則向Redis緩存請(qǐng)求數(shù)據(jù)
3.Redis緩存命中則返回?cái)?shù)據(jù)
4.web服務(wù)器接收到Redis緩存中的數(shù)據(jù)則返回,否則向web服務(wù)發(fā)起讀請(qǐng)求
5.web服務(wù)在堆緩存中查找數(shù)據(jù),命中則返回并緩存到Redis緩存
6.web服務(wù)在堆緩存中未命中數(shù)據(jù),則向DB請(qǐng)求數(shù)據(jù)
7.DB將數(shù)據(jù)返回給web服務(wù)
8.web服務(wù)拿到數(shù)據(jù)后,將數(shù)據(jù)在堆緩存、Redis緩存中保存,并返回web服務(wù)器
web服務(wù)器Nginx本地緩存主要存儲(chǔ)熱點(diǎn)數(shù)據(jù),避免不必要的訪問(wèn)網(wǎng)絡(luò)開(kāi)銷(xiāo)
Redis分布式大規(guī)模緩存,對(duì)應(yīng)的是海量離散數(shù)據(jù)
web服務(wù)的堆緩存是為了避免Redis宕機(jī),導(dǎo)致web服務(wù)器大量的請(qǐng)求涌入,打死DB(雖然效果甚微,總比沒(méi)有要強(qiáng))
數(shù)據(jù)清除策略
一種是對(duì)key設(shè)置存活時(shí)間(TTL),當(dāng)訪問(wèn)的key超過(guò)存活時(shí)間,則返回null并刪除本地?cái)?shù)據(jù)
另一種則是存儲(chǔ)的數(shù)據(jù)量超過(guò)了最大設(shè)置量
以下內(nèi)容為第二種策略
配置
maxmemory 設(shè)置數(shù)據(jù)清除策略開(kāi)始的大小
maxmemory-policy 數(shù)據(jù)滿(mǎn)是所執(zhí)行的策略
noeviction 拒絕寫(xiě)入
allkeys-lru 所有key執(zhí)行LRU
volatile-lru 僅對(duì)設(shè)置了存活時(shí)間(TTL)的key執(zhí)行LRU
allkeys-random 隨機(jī)刪除key
volatile-random 隨機(jī)挑選設(shè)置了存活時(shí)間(TTL)的key刪除
volatile-ttl 移除TTL較短的key
流程
1.外部有寫(xiě)入請(qǐng)求
2.檢查是否超過(guò)maxmemory限制,是則執(zhí)行maxmemory-policy策略清除部分?jǐn)?shù)據(jù)
3.執(zhí)行寫(xiě)入操作
常用策略:allkeys-lru
Redis的LRU清除策略是近似的LRU算法,它通過(guò)采樣采集數(shù)據(jù)進(jìn)行處理而非全量數(shù)據(jù),采樣參數(shù)maxmemory-sample