本文轉(zhuǎn)自互聯(lián)網(wǎng)
本系列文章將整理到我在GitHub上的《Java面試指南》倉庫寂屏,更多精彩內(nèi)容請到我的倉庫里查看
喜歡的話麻煩點下Star哈
文章首發(fā)于我的個人博客:
本文是微信公眾號【Java技術(shù)江湖】的《探索Redis設(shè)計與實現(xiàn)》其中一篇灼狰,本文部分內(nèi)容來源于網(wǎng)絡(luò),為了把本文主題講得清晰透徹碑宴,也整合了很多我認為不錯的技術(shù)博客內(nèi)容,引用其中了一些比較好的博客文章旭等,如有侵權(quán)琅豆,請聯(lián)系作者。
該系列博文會告訴你如何從入門到進階允乐,Redis基本的使用方法矮嫉,Redis的基本數(shù)據(jù)結(jié)構(gòu),以及一些進階的使用方法牍疏,同時也需要進一步了解Redis的底層數(shù)據(jù)結(jié)構(gòu)蠢笋,再接著,還會帶來Redis主從復(fù)制鳞陨、集群昨寞、分布式鎖等方面的相關(guān)內(nèi)容,以及作為緩存的一些使用方法和注意事項厦滤,以便讓你更完整地了解整個Redis相關(guān)的技術(shù)體系援岩,形成自己的知識框架。
如果對本系列文章有什么建議掏导,或者是有什么疑問的話窄俏,也可以關(guān)注公眾號【Java技術(shù)江湖】聯(lián)系作者,歡迎你參與本系列博文的創(chuàng)作和修訂碘菜。
轉(zhuǎn)自https://blog.csdn.net/xlgen157387/article/details/61925524
前言
我們知道Redis是一款內(nèi)存服務(wù)器,就算我們對自己的服務(wù)器足夠的信任,不會出現(xiàn)任何軟件或者硬件的故障忍啸,但也會有可能出現(xiàn)突然斷電等情況仰坦,造成Redis服務(wù)器中的數(shù)據(jù)失效。因此计雌,我們需要向傳統(tǒng)的關(guān)系型數(shù)據(jù)庫一樣對數(shù)據(jù)進行備份悄晃,將Redis在內(nèi)存中的數(shù)據(jù)持久化到硬盤等非易失性介質(zhì)中,來保證數(shù)據(jù)的可靠性凿滤。
將Redis內(nèi)存服務(wù)器中的數(shù)據(jù)持久化到硬盤等介質(zhì)中的一個好處就是妈橄,使得我們的服務(wù)器在重啟之后還可以重用以前的數(shù)據(jù),或者是為了防止系統(tǒng)出現(xiàn)故障而將數(shù)據(jù)備份到一個遠程的位置翁脆。
還有一些場景眷蚓,例如:
對于一些需要進行大量計算而得到的數(shù)據(jù),放置在Redis服務(wù)器反番,我們就有必要對其進行數(shù)據(jù)的持久化沙热,如果需要對數(shù)據(jù)進行恢復(fù)的時候,我們就不需進行重新的計算罢缸,只需要簡單的將這臺機器上的數(shù)據(jù)復(fù)制到另一臺需要恢復(fù)的Redis服務(wù)器就可以了篙贸。
Redis給我們提供了兩種不同方式的持久化方法:快照(Snapshotting) 和 只追加文件(append-only-file)。
(1)名詞簡介
快照(RDB):就是我們俗稱的備份枫疆,他可以在定期內(nèi)對數(shù)據(jù)進行備份爵川,將Redis服務(wù)器中的數(shù)據(jù)持久化到硬盤中;
只追加文件(AOF):他會在執(zhí)行寫命令的時候息楔,將執(zhí)行的寫命令復(fù)制到硬盤里面寝贡,后期恢復(fù)的時候,只需要重新執(zhí)行一下這個寫命令就可以了钞螟。類似于我們的MySQL數(shù)據(jù)庫在進行主從復(fù)制的時候兔甘,使用的是binlog
二進制文件,同樣的是執(zhí)行一遍寫命令鳞滨;
(2)快照持久化通用的配置:
save 60 1000 #60秒時間內(nèi)有1000次寫入操作的時候執(zhí)行快照的創(chuàng)建stop-writes-on-bgsave-error no #創(chuàng)建快照失敗的時候是否仍然繼續(xù)執(zhí)行寫命令rdbcompression yes #是否對快照文件進行壓縮dbfilename dump.rdb #如何命名硬盤上的快照文件dir ./ #快照所保存的位置
(3)AOP持久化配置:
appendonly no #是否使用AOF持久化appendfsync everysec #多久執(zhí)行一次將寫入內(nèi)容同步到硬盤上no-appendfsync-on-rewrite no #對AOF進行壓縮的時候能否執(zhí)行同步操作auto-aof-rewrite-percentage 100 #多久執(zhí)行一次AOF壓縮auto-aof-rewrite-min-size 64mb #多久執(zhí)行一次AOF壓縮dir ./ #AOF所保存的位置
需要注意的是:這兩種持久化的方式既可以單獨的使用洞焙,也可以同時使用,具體選擇哪種方式需要根據(jù)具體的情況進行選擇拯啦。
快照持久化
快照就是我們所說的備份澡匪。用戶可以將Redis內(nèi)存中的數(shù)據(jù)在某一個時間點進行備份,在創(chuàng)建快照之后褒链,用戶可以對快照進行備份唁情。通常情況下,為了防止單臺服務(wù)器出現(xiàn)故障造成所有數(shù)據(jù)的丟失甫匹,我們還可以將快照復(fù)制到其他服務(wù)器甸鸟,創(chuàng)建具有相同數(shù)據(jù)的數(shù)據(jù)副本惦费,這樣的話,數(shù)據(jù)恢復(fù)的時候或者服務(wù)器重啟的時候就可以使用這些快照信息進行數(shù)據(jù)的恢復(fù)抢韭,也可以防止單臺服務(wù)器出現(xiàn)故障的時候造成數(shù)據(jù)的丟失薪贫。
但是,沒我們還需要注意的是刻恭,創(chuàng)建快照的方式瞧省,并不能完全保證我們的數(shù)據(jù)不丟失,這個大家可以很好的理解鳍贾,因為快照的創(chuàng)建時定時的鞍匾,并不是每一次更新操作都會創(chuàng)建一個快照的。系統(tǒng)發(fā)生崩潰的時候骑科,用戶將丟失最近一次生成快照之后更改的所有數(shù)據(jù)橡淑。因此,快照持久化的方式只適合于數(shù)據(jù)不經(jīng)常修改或者丟失部分數(shù)據(jù)影響不大的場景纵散。
一梳码、創(chuàng)建快照的方式:
(1)客戶端通過向Redis發(fā)送BGSAVE
命令來創(chuàng)建快照。
使用BGSAVE的時候伍掀,Redis會調(diào)用fork來創(chuàng)建一個子進程掰茶,然后子進程負責(zé)將快照寫到硬盤中,而父進程則繼續(xù)處理命令請求蜜笤。
使用場景:
如果用戶使用了save設(shè)置濒蒋,例如:save 60 1000
,那么從Redis最近一次創(chuàng)建快照之后開始計算,當(dāng)“60秒之內(nèi)有1000次寫入操作”這個條件滿足的時候把兔,Redis就會自動觸發(fā)BGSAVE命令沪伙。
如果用戶使用了多個save設(shè)置,那么當(dāng)任意一個save配置滿足條件的時候县好,Redis都會觸發(fā)一次BGSAVE命令围橡。
(2)客戶端通過向Redis發(fā)送SAVE
命令來創(chuàng)建快照。
接收到SAVE命令的Redis服務(wù)器在快照創(chuàng)建完畢之前將不再響應(yīng)任何其他命令的請求缕贡。SAVE命令并不常用翁授,我們通常只在沒有足夠的內(nèi)存去執(zhí)行BGSAVE命令的時候才會使用SAVE命令,或者即使等待持久化操作執(zhí)行完畢也無所謂的情況下晾咪,才會使用這個命令收擦;
使用場景:
當(dāng)Redis通過SHUTDOWN命令接收到關(guān)閉服務(wù)器的請求時,或者接收到標準的TERM信號時谍倦,會執(zhí)行一次SAVE命令塞赂,阻塞所有的客戶端,不再執(zhí)行客戶端發(fā)送的任何命令昼蛀,并且在執(zhí)行完SAVE命令之后關(guān)閉服務(wù)器宴猾。
二圆存、使用快照持久化注意事項:
我們在使用快照的方式來保存數(shù)據(jù)的時候,如果Redis服務(wù)器中的數(shù)據(jù)量比較小的話仇哆,例如只有幾個GB的時候辽剧。Redis會創(chuàng)建子進程并將數(shù)據(jù)保存到硬盤里邊,生成快照所需的時間比讀取數(shù)據(jù)所需要的時間還要短税产。
但是,隨著數(shù)據(jù)的增大偷崩,Redis占用的內(nèi)存越來越大的時候辟拷,BGSAVE在創(chuàng)建子進程的時候消耗的時間也會越來越多,如果Redis服務(wù)器所剩下的內(nèi)存不多的時候阐斜,這行BGSAVE命令會使得系統(tǒng)長時間地停頓衫冻,還有可能導(dǎo)致服務(wù)器無法使用。
各虛擬機類別谒出,創(chuàng)建子線程所耗時間:
因此隅俘,為了防止Redis因為創(chuàng)建子進程的時候出現(xiàn)停頓,我們可以考慮關(guān)閉自動保存笤喳,轉(zhuǎn)而通過手動的方式發(fā)送BGSAVE或者SAVE來進行持久化为居,
手動的方式發(fā)送BGSAVE也會出現(xiàn)停頓的現(xiàn)象,但是我們可以控制發(fā)送該命令的時間來控制出現(xiàn)停頓的時候不影響具體的業(yè)務(wù)請求杀狡。
另外蒙畴,值得注意的是,在使用SAVE命令的時候呜象,雖然會一直阻塞Redis直到快照生成完畢膳凝,但是其不需要創(chuàng)建子進程,所以不會向BGSAVE一樣恭陡,因為創(chuàng)建子進程而導(dǎo)致Redis停頓蹬音。也正因為如此,SAVE創(chuàng)建快照的速度要比BGSAVE創(chuàng)建快照的速度更快一些休玩。
創(chuàng)建快照的時候著淆,我們可以在業(yè)務(wù)請求,比較少的時候哥捕,比如凌晨三牧抽、四點,通過手寫腳本的方式遥赚,定時執(zhí)行扬舒。
AOF持久化
AOF持久化會將被執(zhí)行的寫命令寫到AOF文件的末尾,以此來記錄數(shù)據(jù)發(fā)生的變化凫佛。這樣讲坎,我們在恢復(fù)數(shù)據(jù)的時候孕惜,只需要從頭到尾的執(zhí)行一下AOF文件即可恢復(fù)數(shù)據(jù)。
一晨炕、打開AOF持久化選項
我們可以通過使用如下命令打開AOF:
appendonly yes
我們衫画,通過如下命令來配置AOF文件的同步頻率:
appendfsync everysec/always/no
二、appendfsync同步頻率的區(qū)別
appendfsync同步頻率的區(qū)別如下圖:
(1)always的方式固然可以對沒一條數(shù)據(jù)進行很好的保存瓮栗,但是這種同步策略需要對硬盤進行大量的寫操作削罩,所以Redis處理命令的速度會受到硬盤性能的限制。
普通的硬盤每秒鐘只能處理大約200個寫命令费奸,使用固態(tài)硬盤SSD每秒可以處理幾萬個寫命令弥激,但是每次只寫一個命令,這種只能怪不斷地寫入很少量的數(shù)據(jù)的做法有可能引發(fā)嚴重的寫入放大問題愿阐,這種情況下降嚴重影響固態(tài)硬盤的使用壽命微服。
(2)everysec的方式,Redis以每秒一次的頻率大隊AOF文件進行同步缨历。這樣的話既可以兼顧數(shù)據(jù)安全也可以兼顧寫入性能以蕴。
Redis以每秒同步一次AOF文件的性能和不使用任何持久化特性時的性能相差無幾,使用每秒更新一次 的方式辛孵,可以保證丛肮,即使出現(xiàn)故障,丟失的數(shù)據(jù)也在一秒之內(nèi)產(chǎn)生的數(shù)據(jù)觉吭。
(3)no的方式腾供,Redis將不對AOF文件執(zhí)行任何顯示的同步操作,而是由操作系統(tǒng)來決定應(yīng)該何時對AOF文件進行同步鲜滩。
這個命令一般不會對Redis的性能造成多大的影響伴鳖,但是當(dāng)系統(tǒng)出現(xiàn)故障的時候使用這種選項的Redis服務(wù)器丟失不定數(shù)量的數(shù)據(jù)。
另外徙硅,當(dāng)用戶的硬盤處理寫入操作的速度不夠快的話榜聂,那么緩沖區(qū)被等待寫入硬盤的數(shù)據(jù)填滿時,Redis的寫入操作將被阻塞嗓蘑,并導(dǎo)致Redis處理命令請求的速度變慢须肆,因為這個原因,一般不推薦使用這個選項桩皿。
三豌汇、重寫/壓縮AOF文件
隨著數(shù)據(jù)量的增大,AOF的文件可能會很大泄隔,這樣在每次進行數(shù)據(jù)恢復(fù)的時候就會進行很長的時間拒贱,為了解決日益增大的AOF文件,用戶可以向Redis發(fā)送BGREWRITEAOF
命令,這個命令會通過移除AOF文件中的冗余命令來重寫AOF文件逻澳,是AOF文件的體檢變得盡可能的小闸天。
BGREWRITEAOF的工作原理和BGSAVE的原理很像:Redis會創(chuàng)建一個子進程,然后由子進程負責(zé)對AOF文件的重寫操作斜做。
因為AOF文件重寫的時候匯創(chuàng)建子進程苞氮,所以快照持久化因為創(chuàng)建子進程而導(dǎo)致的性能和內(nèi)存占用問題同樣會出現(xiàn)在AOF文件重寫的 時候。
四瓤逼、觸發(fā)重寫/壓縮AOF文件條件設(shè)定
AOF通過設(shè)置auto-aof-rewrite-percentage
和 auto-aof-rewrite-min-size
選項來自動執(zhí)行BGREWRITEAOF笼吟。
其具體含義,通過實例可以看出霸旗,如下配置:
auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb
表示當(dāng)前AOF的文件體積大于64MB赞厕,并且AOF文件的體積比上一次重寫之后的體積變大了至少一倍(100%)的時候,Redis將執(zhí)行重寫B(tài)GREWRITEAOF命令定硝。
如果AOF重寫執(zhí)行的過于頻繁的話,可以將auto-aof-rewrite-percentage
選項的值設(shè)置為100以上毫目,這種最偶發(fā)就可以讓Redis在AOF文件的體積變得更大之后才執(zhí)行重寫操作蔬啡,不過,這也使得在進行數(shù)據(jù)恢復(fù)的時候執(zhí)行的時間變得更加長一些镀虐。
驗證快照文件和AOF文件
無論使用哪種方式進行持久化箱蟆,我們在進行恢復(fù)數(shù)據(jù)的時候,Redis提供了兩個命令行程序:
redis-check-aofredis-check-dump
他們可以再系統(tǒng)發(fā)生故障的時候刮便,檢查快照和AOF文件的狀態(tài)空猜,并對有需要的情況對文件進行修復(fù)。
如果用戶在運行redis-check-aof命令的時候恨旱,指定了--fix
參數(shù)辈毯,那么程序?qū)OF文件進行修復(fù)。
程序修復(fù)AOF文件的方法很簡單:他會掃描給定的AOF文件搜贤,尋找不正確或者不完整的命令谆沃,當(dāng)發(fā)現(xiàn)第一個出現(xiàn)錯誤命令的時候,程序會刪除出錯命令以及出錯命令之后的所有命令仪芒,只保留那些位于出錯命令之前的正確命令唁影。大部分情況,被刪除的都是AOF文件末尾的不完整的寫命令掂名。
總結(jié)
上述据沈,一起學(xué)習(xí)了兩種支持持久化的方式,一方面我們需要通過快照或者AOF的方式對數(shù)據(jù)進行持久化饺蔑,另一方面锌介,我們還需要將持久化所得到的文件進行備份,備份到不同的服務(wù)器上膀钠,這樣才可以盡可能的減少數(shù)據(jù)丟失的損失掏湾。
參考文章:
1裹虫、Redis in Action - [美] Josiah L.Carlsono