介紹
? 持久化的功能:Redis是內(nèi)存數(shù)據(jù)庫,數(shù)據(jù)都是存儲在內(nèi)存中叁怪,為了避免進程退出導致數(shù)據(jù)的永久丟失泳叠,需要定期將Redis中的數(shù)據(jù)以某種形式(數(shù)據(jù)或命令)從內(nèi)存保存到硬盤中。當下次Redis重啟時,利用持久化文件實現(xiàn)數(shù)據(jù)恢復菜拓。除此之外,為了進行災(zāi)難備份笛厦,可以將持久化文件拷貝到一個遠程位置纳鼎。Redis持久化分為RDB和AOF,前者將當前數(shù)據(jù)保存到硬盤裳凸,后者則是將每次執(zhí)行的寫命令保存的硬盤贱鄙。
RDB持久化
? RDB是一種快照存儲持久方式,具體就是將Redis某一時刻的內(nèi)存數(shù)據(jù)保存到硬盤的文件當中姨谷,默認保存的文件名為dump.rdb逗宁,而在Redis服務(wù)器啟動時,會重新加載dump.rdb文件的數(shù)據(jù)到內(nèi)存當中恢復數(shù)據(jù)梦湘。觸發(fā)RDB持久化過程分為手動觸發(fā)和自動觸發(fā)瞎颗。
觸發(fā)機制
手動觸發(fā)分別對應(yīng)save
和bgsave
命令:
save
命令:阻塞當前Redis服務(wù)器件甥,直到RDB過程完成為止,對于內(nèi)存比較大的實例會造成長時間阻塞哼拔,線上環(huán)境不建議使用引有。
bgsave
命令:Redis進程執(zhí)行fork操作創(chuàng)建子進程,RDB持久化過程由子進程負責倦逐,完成后自動結(jié)束譬正。阻塞只發(fā)生在fork階段,一般時間很短檬姥。
顯示bgsave
命令是針對save
阻塞問題做的優(yōu)化曾我。因此Redis內(nèi)部所有的涉及RDB的操作都采用bgsave
的方式。
除了執(zhí)行命令手動觸發(fā)之外健民,Redis內(nèi)部還存在自動觸發(fā)RDB的持久化機制您单,例如以下場景:
- 使用
save
相關(guān)配置,如save m n
荞雏。表示m秒內(nèi)數(shù)據(jù)集存在n次修改時虐秦,自動觸發(fā)bgsave
。 - 如果從節(jié)點執(zhí)行全量復制操作凤优,主節(jié)點自動執(zhí)行
bgsave
生成RDB文件并發(fā)送給從節(jié)點悦陋。 - 執(zhí)行
debug reload
命令重載Redis時,也會自動觸發(fā)save
操作筑辨。 - 默認情況下執(zhí)行
shutdown
命令時俺驶,如果沒有開啟AOF持久化功能則自動執(zhí)行bgsave
。
執(zhí)行流程
bgsave
是主流的觸發(fā)RDB持久化方式:
- 執(zhí)行
bgsave
命令棍辕,Redis父進程判斷當前是否存在正在執(zhí)行的子進程暮现,如RDB/AOF子進程,如果存在bgsave
命令直接返回楚昭。 - 父進程執(zhí)行fork操作創(chuàng)建子進程栖袋,fork操作過程中父進程會阻塞,通過
info stats
命令查看latest_fork_usec
選項抚太,可以獲得最近一個fork操作的耗時塘幅,單位為微妙。 - 父進程fork完成后尿贫,
bgsave
命令返回Background saving started信息并不再阻塞父進程电媳,可以繼續(xù)響應(yīng)其它命令。 - 子進程創(chuàng)建RDB文件庆亡,根據(jù)父進程內(nèi)存生成臨時快照文件匾乓,完成后原有文件進行原子替換。執(zhí)行
lastsave
命令可以獲取最后一次生成RDB的時間又谋,對應(yīng)info
統(tǒng)計的rdb_last_save_time
選項拼缝。 - 進程發(fā)送信號給父進程表示完成括享,父進程更新統(tǒng)計信息,具體見
info Persistence
下的rdb_*
相關(guān)選項珍促。
服務(wù)器配置自動觸發(fā)
? 除了通過客戶端發(fā)送命令外铃辖,還有一種方式,就是在Redis配置文件中的save
指定到達觸發(fā)RDB持久化的條件猪叙,比如【多少秒內(nèi)至少達到多少寫操作】就開啟RDB數(shù)據(jù)同步娇斩。
例如我們可以在配置文件redis.conf指定如下的選項:
# 900s內(nèi)至少達到1條寫命令
save 900 1
# 300s內(nèi)至少達到10條寫命令
save 300 10
# 60s內(nèi)至少達到1000條寫命令
save 60 1000
這種通過服務(wù)器配置文件觸發(fā)RDB的方式,與bgsave
命令類似穴翩,達到觸發(fā)條件時犬第,會fork一個子進程進行數(shù)據(jù)同步,不過最好不要通過這種方式來觸發(fā)RDB持久化芒帕,因為設(shè)置觸發(fā)的時間太短歉嗓,則容易頻繁寫入rdb文件,影響服務(wù)器性能背蟆,時間設(shè)置太長會造成數(shù)據(jù)丟失鉴分。
RDB文件的處理
保存:
-
RDB文件保存在dir配置指定的目錄下,文件名通過dbfilename配置指定带膀≈菊洌可通過執(zhí)行
config set dir {newDir}
和config set dbfilename {newFileName}
運行期動態(tài)執(zhí)行,當下次運行時RDB文件會保存到新目錄垛叨。
壓縮:
-
Redis默認采用LZF算法對生存的RDB文件做壓縮處理伦糯,壓縮后的文件遠遠小于內(nèi)存大小,默認開啟嗽元,可以通過參數(shù)
config set rdbcompression {yes|no}
動態(tài)修改敛纲。 - 雖然壓縮RDB會消耗CPU,但可大幅度降低文件的體積剂癌,方便保存到硬盤或通過網(wǎng)絡(luò)發(fā)送給從節(jié)點淤翔,因此線上建議開啟。
RDB方式的優(yōu)缺點
優(yōu)點:
- RDB是一個非常緊湊的文件珍手,它保存了Redis在某個時間點上的數(shù)據(jù)集办铡。這種文件非常適合用于備份;比如說琳要,你可以在最近的24小時內(nèi),每小時備份一次RDB文件秤茅,并且在每個月的每一天稚补,也備份一個RDB文件。這樣的話框喳,即使遇上問題课幕,也可以隨時將數(shù)據(jù)集還原到不同的版本厦坛。
- RDB可以最大化Redis的性能锌蓄;父進程在保存RDB文件時唯一要做的就是fork出一個子進程账嚎,然后這個子進程就會處理接下來的所有保存工作浑度,父進程無需執(zhí)行任何磁盤I/O操作甥捺。
- RDB在恢復大數(shù)據(jù)集時的速度要比AOF的恢復速度快享言。
缺點:
- RDB方式數(shù)據(jù)沒辦法做到實時持久化/秒級持久化罪治。如果服務(wù)器宕機的話图甜,采用RDB的方式會造成某個時段內(nèi)數(shù)據(jù)的丟失底靠,比如我們設(shè)置10分鐘同步一次或者5分鐘達到1000次寫入就同步一次莉撇,那么如果還沒達到觸發(fā)條件服務(wù)器就死機了呢蛤,那么這個時間段的數(shù)據(jù)會丟失。
- 使用
bgsave
命令在fork子進程時棍郎,如果數(shù)據(jù)量太大其障,fork的過程也會發(fā)生阻塞,另外涂佃,fork子進程會消耗內(nèi)存励翼。針對RDB不適合做實時持久化的問題,Redis提供了AOF持久化方式來解決辜荠。
AOF持久化
? AOF(append only file)持久化抚笔;與RDB存儲某個時刻的快照不同,AOF持久化方式會記錄客戶端對服務(wù)器的每一次寫操作命令到日志當中侨拦,并將這些操作以Redis協(xié)議追加保存到以后綴為aof文件末尾殊橙。
使用AOF
? 開啟AOF功能需要設(shè)置配置;appendonly yes
狱从,默認不開啟膨蛮。AOF文件名通過appendfilename
配置設(shè)置,默認文件名是appendonly.aof季研。保存路徑同RDB持久化方式一致敞葛,通過dir配置指定。
持久化配置
appendonly yes #啟用aof持久化方式
appendfsync always #每次收到命令就立即強制寫入磁盤与涡,最慢的大概只有幾百的TPS惹谐,但是保證完全的持久化,不推薦使用
appendfsync everysec #每秒鐘強制寫入磁盤一次驼卖,在性能和持久化方面做了很好的折中氨肌,推薦
appendfsync no #完全依賴os,性能最好酌畜,持久化沒保證怎囚,Redis不會主動調(diào)用fsync去將AOF日志內(nèi)容同步到磁盤,所以這一切完全依賴于操作系統(tǒng)的調(diào)試了桥胞。對于大多數(shù)Linux操作系統(tǒng)恳守,是每30s進行一次fsync考婴,將緩沖區(qū)中的數(shù)據(jù)寫的磁盤上。
執(zhí)行流程
- 所以的寫入命令會追加到aof_buf(緩沖區(qū))中催烘。
- AOF緩沖區(qū)根據(jù)對應(yīng)的策略向硬盤做同步操作沥阱。
- 隨著AOF文件越來越大,需要定期對AOF文件進行重寫伊群,達到壓縮的目的考杉。
- 當Redis服務(wù)器重啟時,可以加載AOF文件進行數(shù)據(jù)恢復在岂。
在同步期間可能會發(fā)生阻塞問題
- 若果AOF文件fsync同步時間大于2s奔则,Redis主進程就會阻塞。
- 若果AOF文件fsync同步時間小于2s蔽午,Redis主進程就會返回易茬。
其實這樣做是為了保證文件安全性的一種策略。
AOF追加阻塞會產(chǎn)生的問題:
- fsync大于2s時候及老,會阻塞redis主進程抽莱,我們都知道redis主進程是用來執(zhí)行redis命令的,是不能阻塞的骄恶。
- 雖然每秒everysec刷盤策略食铐,但是實際上不是丟失1s數(shù)據(jù),實際有可能丟失2s數(shù)據(jù)僧鲁。
重寫機制
AOF將客戶端的每一個寫操作都追加到aof文件末尾虐呻,隨著命令不斷寫入AOF,文件會越來越大寞秃,為了解決這個問題斟叼,Redis引入AOF重寫機制壓縮文件體積。
-
AOF文件重寫是吧Redis進程內(nèi)的數(shù)據(jù)轉(zhuǎn)化為寫命令同步到新AOF文件的過程春寿。
比如:多條命令可以合并為一個朗涩,
lpush list a、lpush list b
可以轉(zhuǎn)化為lpush list a b
绑改。 AOF重寫降低了文件占用空間谢床,除此之外,另一個目的是:更小的AOF文件可以更快地被加載厘线。
觸發(fā)機制:
AOF重寫過程可以手動觸發(fā)和自動觸發(fā):
- 手動觸發(fā):直接調(diào)用
bgrewriteaof
命令识腿。 - 自動觸發(fā):根據(jù)
auto-aof-rewrite-min-size
和auto-aof-rewrite-percentage
參數(shù)確定自動觸發(fā)。-
auto-aof-rewrite-min-size
表示運行AOF重寫時文件最小體積皆的,默認為64MB覆履。 -
auto-aof-rewrite-percentage
代表當前AOF文件空間(aof_current_size)和上一次重寫后AOF文件空間(aof_base_size)的比值。
-
- 示例:
auto-aof-rewrite-percentage:100
auto-aof-rewrite-min-size:64mb
- 默認配置時當AOF文件大小是上次rewrite后大小的一倍且文件大于64mb時觸發(fā)费薄。
當觸發(fā)AOF重寫時硝全,內(nèi)部流程:
執(zhí)行AOF重寫請求。如果當前進程正在執(zhí)行AOF重寫楞抡,請求不執(zhí)行并返回如下響應(yīng):ERR Background append only file rewriting already in progress
- 父進程執(zhí)行fork創(chuàng)建子進程伟众,開銷等同于bgsave過程。
- 主進程fork操作完成后召廷,繼續(xù)響應(yīng)其它命令凳厢。所以修改命令依然寫入AOF緩沖區(qū)并根據(jù)
appendfsync
策略同步到硬盤,保證原有AOF機制正確性竞慢。 - 由于fork操作運用寫時復制技術(shù)先紫,子進程只能共享fork操作時的內(nèi)存數(shù)據(jù)。由于父進程依然響應(yīng)命令筹煮,Redis使用AOF重寫緩沖區(qū)保存這部分新數(shù)據(jù)遮精,防止新AOF文件生成期間丟失這部分數(shù)據(jù)。
- 主進程fork操作完成后召廷,繼續(xù)響應(yīng)其它命令凳厢。所以修改命令依然寫入AOF緩沖區(qū)并根據(jù)
- 子進程根據(jù)內(nèi)存快照败潦,按照命令合并規(guī)則寫入新的AOF文件本冲,每次批量寫入硬盤數(shù)據(jù)量由配置
aof-rewrite-incremental-fsync
控制,默認為32MB劫扒,防止單詞刷盤數(shù)據(jù)過多造成硬盤阻塞檬洞。- 新AOF文件寫入完成后,子進程發(fā)送信號給父進程沟饥,父進程更新統(tǒng)計信息添怔,具體見
info persistence
的aof_*相關(guān)統(tǒng)計。 - 父進程把AOF重寫緩沖區(qū)的數(shù)據(jù)寫入到新的AOF文件贤旷。
- 使用新AOF文件替換老文件广料,完成AOF重寫。
- 新AOF文件寫入完成后,子進程發(fā)送信號給父進程沟饥,父進程更新統(tǒng)計信息添怔,具體見
注意事項
? 在寫入AOF日志文件時遮晚,如果Redis服務(wù)器宕機性昭,則aof日志文件會出現(xiàn)格式錯誤,在重啟Redis服務(wù)器時县遣,Redis服務(wù)器會拒絕載入這個aof文件糜颠,可以通過命令修復aof并恢復數(shù)據(jù)。
redid-check-aof -fix appendonly.aof
AOF的優(yōu)缺點
優(yōu)點:
- AOF可以設(shè)置完全不同步萧求、每秒同步其兴、每次操作同步,默認時每秒同步夸政。因為AOF時操作指令的追加元旬,所以可以頻繁的大量的同步。
- AOF文件是一個值追加日志的文件,即使服務(wù)宕機為寫入完整的命令匀归,也可以通過redis-check-aof工具修復這些問題坑资。
- 如果AOF文件過大,Redis會在后臺自動地重寫AOF文件穆端。重寫后會使AOF文件壓縮到最小所需的指令集袱贮。
-
AOF文件是有序保存數(shù)據(jù)看的所有寫入操作,易讀体啰,易分析攒巍。即使如果不小心誤操作數(shù)據(jù)看,也很容易找出業(yè)務(wù)錯誤指令荒勇,恢復到某個數(shù)據(jù)節(jié)點柒莉。例如不小
FLUSHALL
,可以非常容易恢復到執(zhí)行命令之前沽翔。
缺點:
- 相同數(shù)據(jù)量下兢孝,AOF的文件通常體積會比RDB大。因為AOF是存指令的搀擂,而RDB是所有指令的結(jié)果快照西潘。但AOF在日志重寫后會壓縮一些空間。
- 在大量寫入和載入的時候哨颂,AOF的效率會比RDB低喷市,因為大量寫入,AOF會執(zhí)行更多的保存命令威恼,載入的時候也需要大量的重執(zhí)行命令來得到最后的結(jié)果品姓。RDB對此更有優(yōu)勢。
AOF常用配置
appendonly no
:是否開啟AOF
appendfilename "appendonly.aof"
:AOF文件名
dir ./
:RDB文件和AOF文件所在目錄
appendfsync everysec
:fsync持久化策略
no-appendfsync-on-rewrite no
:AOF重寫期間是否禁止fsync箫措;如果開啟該選項腹备,可以減輕文件重寫時CPU和硬盤的負載(尤其是硬盤),但是可能會丟失AOF重寫期間的數(shù)據(jù)斤蔓;需要在負載和安全性之間進行平衡
auto-aof-rewrite-percentage 100
:文件重寫觸發(fā)條件之一
auto-aof-rewrite-min-size 64mb
:文件重寫觸發(fā)提交之一
aof-load-truncated yes
:如果AOF文件結(jié)尾損壞植酥,Redis啟動時是否仍載入AOF文件
重啟加載的選擇
AOF和RDB文件都可以用于服務(wù)器重啟時的數(shù)據(jù)恢復。
持久化的選擇
? 在實際生產(chǎn)環(huán)境中弦牡,根據(jù)數(shù)據(jù)量友驮、應(yīng)用對數(shù)據(jù)的安全要求、預算限制等不同情況驾锰,會有各種各樣的持久化策略卸留;如完全不使用任何持久化、使用RDB或AOF的一種椭豫,或同時開啟RDB和AOF持久化等耻瑟。
? 此外旨指,持久化的選擇必須與Redis的主從策略一起考慮,因為主從復制與持久化同樣具有數(shù)據(jù)備份的功能喳整,而且主機master和從機slave可以獨立的選擇持久化方案谆构。
面分場景來討論持久化策略的選擇,下面的討論也只是作為參考算柳,實際方案可能更復雜更具多樣性低淡。
- 如果Redis中的數(shù)據(jù)完全丟棄也沒有關(guān)系(如Redis完全用作DB層數(shù)據(jù)的cache)姓言,那么無論是單機瞬项,還是主從架構(gòu),都可以不進行任何持久化何荚。
- 在單機環(huán)境下(對于個人開發(fā)者囱淋,這種情況可能比較常見),如果可以接受十幾分鐘或更多的數(shù)據(jù)丟失餐塘,選擇RDB對Redis的性能更加有利妥衣;如果只能接受秒級別的數(shù)據(jù)丟失,應(yīng)該選擇AOF戒傻。
- 但在多數(shù)情況下税手,我們都會配置主從環(huán)境,slave的存在既可以實現(xiàn)數(shù)據(jù)的熱備需纳,也可以進行讀寫分離分擔Redis讀請求芦倒,以及在master宕掉后繼續(xù)提供服務(wù)。在這種情況下的做法是:
- master:完全關(guān)閉持久化(包括RDB和AOF)不翩,這樣可以讓master的性能達到最好兵扬;
- slave:關(guān)閉RDB,開啟AOF(如果對數(shù)據(jù)安全要求不高口蝠,開啟RDB關(guān)閉AOF也可以)器钟,并定時對持久化文件進行備份(如備份到其他文件夾,并標記好備份的時間)妙蔗;然后關(guān)閉AOF的自動重寫傲霸,然后添加定時任務(wù),在每天Redis閑時(如凌晨12點)調(diào)用
bgrewriteaof
眉反。 - 這里需要解釋一下昙啄,為什么開啟了主從復制,可以實現(xiàn)數(shù)據(jù)的熱備份禁漓,還需要設(shè)置持久化呢跟衅?因為在一些特殊情況下,主從復制仍然不足以保證數(shù)據(jù)的安全播歼,例如:
- master和slave進程同時停止:考慮這樣一種場景伶跷,如果master和slave在同一個機房掰读,則一次停電事故就可能導致master和slave機器同時關(guān)機,Redis進程停止叭莫;如果沒有持久化蹈集,則面臨的是數(shù)據(jù)的完全丟失。
- master誤重啟:考慮這樣一種場景雇初,master服務(wù)因為故障宕掉了拢肆,如果系統(tǒng)中有自動拉起機制(即檢測到服務(wù)停止后重啟該服務(wù))將master自動重啟,由于沒有持久化文件靖诗,那么master重啟后數(shù)據(jù)是空的郭怪,slave同步數(shù)據(jù)也變成了空的;如果master和slave都沒有持久化刊橘,同樣會面臨數(shù)據(jù)的完全丟失鄙才。需要注意的是,即便是使用了哨兵進行自動的主從切換促绵,也有可能在哨兵輪詢到master之前攒庵,便被自動拉起機制重啟了。因此败晴,應(yīng)盡量避免“自動拉起機制”和“不做持久化”同時出現(xiàn)浓冒。
- 異地災(zāi)備:上述討論的幾種持久化策略,針對的都是一般的系統(tǒng)故障尖坤,如進程異常退出稳懒、宕機、斷電等糖驴,這些故障不會損壞硬盤僚祷。但是對于一些可能導致硬盤損壞的災(zāi)難情況,如火災(zāi)地震贮缕,就需要進行異地災(zāi)備辙谜。
- 例如對于單機的情形,可以定時將RDB文件或重寫后的AOF文件感昼,通過scp拷貝到遠程機器装哆,如阿里云;對于主從的情形定嗓,可以定時在master上執(zhí)行
bgsave
蜕琴,然后將RDB文件拷貝到遠程機器,或者在slave上執(zhí)行bgrewriteaof
重寫AOF文件后宵溅,將AOF文件拷貝到遠程機器上凌简。 - 一般來說,由于RDB文件文件小恃逻、恢復快雏搂,因此災(zāi)難恢復常用RDB文件藕施;異地備份的頻率根據(jù)數(shù)據(jù)安全性的需要及其它條件來確定,但最好不要低于一 天一次凸郑。
- 例如對于單機的情形,可以定時將RDB文件或重寫后的AOF文件感昼,通過scp拷貝到遠程機器装哆,如阿里云;對于主從的情形定嗓,可以定時在master上執(zhí)行
持久化配置方案
-
企業(yè)級的持久化的配置策略
-
save 60 10000
:如果你希望盡可能確保說裳食,RDB最多丟1分鐘的數(shù)據(jù),那么盡量就是每隔1分鐘都生成一個快照芙沥,低峰期诲祸,數(shù)據(jù)量很少,也沒必要 10000->生成RDB而昨,1000->RDB救氯,這個根據(jù)你自己的應(yīng)用和業(yè)務(wù)的數(shù)據(jù)量,自己去決定 - AOF一定要打開配紫。
-
auto-aof-rewrite-percentage 100
: 就是當前AOF大小膨脹到超過上次100%径密,上次的兩倍 -
auto-aof-rewrite-min-size 64mb
: 根據(jù)你的數(shù)據(jù)量來定,16mb躺孝,32mb
-
-
數(shù)據(jù)備份方案 RDB非常適合做冷備,每次生成之后底桂,就不會再有修改了
- 寫crontab定時調(diào)度腳本去做數(shù)據(jù)備份
- 每小時都copy一份rdb的備份植袍,到一個目錄中去,僅僅保留最近48小時的備份
- 每天都保留一份當日的rdb的備份籽懦,到一個目錄中去于个,僅僅保留最近1個月的備份
- 每次copy備份的時候,都把太舊的備份給刪了
- 每天晚上將當前服務(wù)器上所有的數(shù)據(jù)備份暮顺,發(fā)送一份到遠程的云服務(wù)上去【crontab】