【面題解析】覺(jué)得自己精通Redis的,看過(guò)持久化的配置嗎?

源 / 文/ 阿Q
Redis持久化的神秘面紗。Redis有兩種持久化方案,一種是快照方式(SNAPSHOTTING),簡(jiǎn)稱(chēng)RDB;一種是只追加模式(APPEND ONLY MODE),稱(chēng)為AOF。接下來(lái)讓我們分別了解一下它們的使用與注意事項(xiàng)。RDB
RDB為Redis DataBase的縮寫(xiě),是 Redis 默認(rèn)的持久化方案。它能夠在指定的時(shí)間間隔內(nèi)將內(nèi)存數(shù)據(jù)集快照(snapshot)寫(xiě)入磁盤(pán),恢復(fù)時(shí)將快照文件( dump.rdb )讀回內(nèi)存。
SNAPSHOTTING:配置文件
save <seconds> <changes>
Redis默認(rèn)配置文件中提供了三個(gè)條件:save 900 1 //900s內(nèi)有1個(gè)更改
save 300 10 //300s內(nèi)有10個(gè)更改
save 60 10000 //60s內(nèi)有10000次更改
RDB方案,可以把 save ""的注釋打開(kāi),上邊三個(gè)注釋掉。stop-writes-on-bgsave-error yes
bgsave出現(xiàn)錯(cuò)誤時(shí),Redis是否停止執(zhí)行寫(xiě)命令;如果為 yes,則當(dāng)硬盤(pán)出現(xiàn)問(wèn)題時(shí),Redis將停止接受寫(xiě)入操作,這樣我們可以及時(shí)發(fā)現(xiàn),避免數(shù)據(jù)的大量丟失;如果為 no,則Redis無(wú)視bgsave的錯(cuò)誤繼續(xù)執(zhí)行寫(xiě)命令。
如果已經(jīng)設(shè)置了對(duì) Redis服務(wù)器的正確監(jiān)視和持久性,即采用了其他手段發(fā)現(xiàn)和控制數(shù)據(jù)完整性,可能希望禁用此功能,以便即使在磁盤(pán)、權(quán)限等方面出現(xiàn)問(wèn)題時(shí),Redis仍能正常工作。
Redis將自動(dòng)允許再次寫(xiě)入。rdbcompression yes
Redis采用LZF壓縮)數(shù)據(jù),默認(rèn)為yes。如果為了節(jié)省CPU時(shí)間,可以關(guān)閉該選項(xiàng),但會(huì)導(dǎo)致數(shù)據(jù)庫(kù)文件變得巨大。rdbchecksum yes
RDB版本5開(kāi)始,在存儲(chǔ)快照后,還可以使用CRC64算法來(lái)進(jìn)行數(shù)據(jù)校驗(yàn),CRC64校驗(yàn)放在文件的末尾。開(kāi)啟之后,保存和加載RDB文件時(shí)會(huì)增加大約10%的性能消耗,如果希望獲取到最大的性能提升,可以關(guān)閉此功能。RDB文件的校驗(yàn)和為零,這將告訴加載代碼跳過(guò)檢查。dbfilename dump.rdb
save 命令的話即刻生效。大坑請(qǐng)注意: flushall、shutdown命令都會(huì)清空并提交至dump.rdb
dir ./
理論
工作方式
當(dāng) Redis需要保存dump.rdb文件時(shí),它會(huì)調(diào)用系統(tǒng)函數(shù)fork(),創(chuàng)建一個(gè)子進(jìn)程(與主進(jìn)程完全一致);子進(jìn)程將數(shù)據(jù)集寫(xiě)入臨時(shí)文件 RDB中;當(dāng)子進(jìn)程完成對(duì)新 RDB文件的寫(xiě)入時(shí),Redis用新RDB文件替換原來(lái)的RDB文件,并刪除舊的RDB文件。
Redis 可以從寫(xiě)時(shí)復(fù)制(copy-on-write)機(jī)制中獲益。如何觸發(fā)RDB快照
配置文件中默認(rèn)的快照配置; 命令 save(阻塞, 只管保存快照,其他的等待)或者是bgsave(異步)命令,快照同時(shí)還可以響應(yīng)客戶(hù)端命令;執(zhí)行 flushall命令,清空數(shù)據(jù)庫(kù)所有數(shù)據(jù),意義不大;執(zhí)行 shutdown命令,保證服務(wù)器正常關(guān)閉且不丟失任何數(shù)據(jù),意義也不大。
通過(guò)RDB文件恢復(fù)數(shù)據(jù)
dump.rdb文件。將備份的dump.rdb 文件拷貝到redis的安裝目錄的bin目錄下,重啟redis服務(wù)即可。優(yōu)點(diǎn)
RDB是一個(gè)非常緊湊的文件,非常適用于數(shù)據(jù)集的備份;RDB是一個(gè)緊湊的單一文件,很方便傳送到另一個(gè)遠(yuǎn)端數(shù)據(jù)中心或者亞馬遜的S3(可能加密),非常適用于災(zāi)難恢復(fù);Redis的主進(jìn)程不進(jìn)行I/O操作,確保了極高的性能;適合大規(guī)模數(shù)據(jù)的恢復(fù),對(duì)于數(shù)據(jù)的完整性和一致性要求不高的話, RDB比AOF方式更加高效。
缺點(diǎn)
在 Redis意外宕機(jī)時(shí),你可能會(huì)丟失幾分鐘的數(shù)據(jù);RDB需要經(jīng)常fork子進(jìn)程來(lái)保存數(shù)據(jù)集到硬盤(pán)上,當(dāng)數(shù)據(jù)集比較大的時(shí)候,fork的過(guò)程是非常耗時(shí)的,可能會(huì)導(dǎo)致Redis在一些毫秒級(jí)內(nèi)不能響應(yīng)客戶(hù)端的請(qǐng)求。如果數(shù)據(jù)集巨大并且CPU性能不是很好的情況下,這種情況會(huì)持續(xù)1秒;AOF也需要fork,但是可以調(diào)節(jié)重寫(xiě)日志文件的頻率來(lái)提高數(shù)據(jù)集的耐久度。
AOF
RDB方式在宕機(jī)時(shí)丟失數(shù)據(jù)過(guò)多的問(wèn)題,從1.1 版本開(kāi)始,Redis增加了一種durable的持久化方式:AOF。AOF是Append Only File的縮寫(xiě),默認(rèn)不開(kāi)啟。AOF以日志的形式來(lái)記錄每個(gè)寫(xiě)操作,只允許追加文件但不可以改寫(xiě)文件,當(dāng)服務(wù)器重啟的時(shí)候會(huì)重新執(zhí)行這些命令來(lái)恢復(fù)原始的數(shù)據(jù)。APPEND ONLY MODE:配置文件
appendonly no
yes打開(kāi)持久化。AOF和RDB可以同時(shí)啟用而不會(huì)出現(xiàn)問(wèn)題。appendfilename "appendonly.aof"
dump.rdb文件appendfsync
fsync() 告訴操作系統(tǒng)在磁盤(pán)上實(shí)際寫(xiě)入數(shù)據(jù)。Redis支持三種不同的模式appendfsync always //每次發(fā)生數(shù)據(jù)變更會(huì)被立即記錄到磁盤(pán),性能較差但數(shù)據(jù)完整性比較好
appendfsync everysec //默認(rèn)推薦,異步操作,每秒記錄,如果宕機(jī),有1秒內(nèi)數(shù)據(jù)丟失
appendfsync no //不同步,只有在操作系統(tǒng)需要時(shí)在刷新數(shù)據(jù)
重寫(xiě)
AOF采用的是將命令追加到文件末尾的方式,所以隨著寫(xiě)入命令的不斷增加,AOF文件的體積會(huì)變得越來(lái)越大。為避免出現(xiàn)此種情況,新增了重寫(xiě)機(jī)制:可以在不打斷服務(wù)客戶(hù)端的情況下,對(duì)AOF文件進(jìn)行重建(rebuild)。bgrewriteaof命令,可以生成一個(gè)新的AOF文件,該文件包含重建當(dāng)前數(shù)據(jù)集所需的最少命令。Redis 2.2需手動(dòng)執(zhí)行該命令,Redis 2.4則可以通過(guò)修改配置文件的方式自動(dòng)觸發(fā)(配置在下邊涉及)。Redis執(zhí)行系統(tǒng)函數(shù)fork(),創(chuàng)建一個(gè)子進(jìn)程(與主進(jìn)程完全一致);子進(jìn)程開(kāi)始將新 AOF文件的內(nèi)容寫(xiě)入到臨時(shí)文件;對(duì)于所有新執(zhí)行的寫(xiě)入命令,父進(jìn)程一邊將它們累積到一個(gè)內(nèi)存緩存中,一邊將這些改動(dòng)追加到現(xiàn)有 AOF文件的末尾,這樣即使在重寫(xiě)的中途發(fā)生停機(jī),現(xiàn)有的AOF文件也是安全的;當(dāng)子進(jìn)程完成重寫(xiě)工作時(shí),它給父進(jìn)程發(fā)送一個(gè)信號(hào),父進(jìn)程在接收到信號(hào)之后,將內(nèi)存緩存中的所有數(shù)據(jù)追加到新 AOF文件的末尾。Redis原子地用新文件替換舊文件,之后所有命令都會(huì)直接追加到新AOF文件的末尾。
no-appendfsync-on-rewrite no
aof文件的時(shí)候出現(xiàn)阻塞的情形。no-appendfsync-on-rewrite參數(shù)出場(chǎng)了。如果該參數(shù)設(shè)置為 no,是最安全的方式,不會(huì)丟失數(shù)據(jù),但是要忍受阻塞的問(wèn)題;如果設(shè)置為 yes,這就相當(dāng)于將appendfsync設(shè)置為no,這說(shuō)明并沒(méi)有執(zhí)行磁盤(pán)操作,只是寫(xiě)入了緩沖區(qū)。因此這樣并不會(huì)造成阻塞(因?yàn)闆](méi)有競(jìng)爭(zhēng)磁盤(pán)),但是如果這個(gè)時(shí)候redis掛掉,就會(huì)丟失數(shù)據(jù)。丟失多少數(shù)據(jù)呢?在linux的操作系統(tǒng)的默認(rèn)設(shè)置下,最多會(huì)丟失30s的數(shù)據(jù)。
yes;如果應(yīng)用系統(tǒng)無(wú)法忍受數(shù)據(jù)丟失,則設(shè)置為no。auto-aof-rewrite-percentage 100
aof文件大小的一倍。auto-aof-rewrite-min-size 64mb
auto-aof-rewrite-min-size和auto-aof-rewrite-percentage參數(shù)確定自動(dòng)觸發(fā)時(shí)機(jī)。Redis會(huì)記錄上次重寫(xiě)時(shí)的AOF大小,默認(rèn)配置是當(dāng)AOF文件大小是上次rewrite后大小的一倍且文件大于64M時(shí)觸發(fā)。大型互聯(lián)網(wǎng)公司一般都是 3G起步
aof-load-truncated yes
AOF文件被截?cái)鄷r(shí),即AOF文件的最后命令不完整,如果此時(shí)啟動(dòng)Redis,會(huì)將AOF數(shù)據(jù)加載回內(nèi)存,此時(shí)便會(huì)出現(xiàn)問(wèn)題。yes:加載一個(gè)截?cái)嗟?code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">AOF, Redis服務(wù)器開(kāi)始發(fā)出日志,通知用戶(hù)該事件;no:服務(wù)器將中止并出現(xiàn)錯(cuò)誤,拒絕啟動(dòng)。
AOF文件報(bào)錯(cuò)時(shí),可以用以下方法來(lái)修復(fù)出錯(cuò)的 AOF 文件:為現(xiàn)有的 AOF文件創(chuàng)建一個(gè)備份;使用 Redis附帶的redis-check-aof命令,對(duì)原來(lái)的AOF文件進(jìn)行修復(fù);redis-check-aof –fixredis-check-aof --fix appendonly.aof修復(fù)命令,殺光不符合規(guī)范的語(yǔ)法(可選)使用 diff -u對(duì)比修復(fù)后的AOF文件和原始AOF文件的備份,查看兩個(gè)文件之間的不同之處;重啟 Redis服務(wù)器,等待服務(wù)器載入修復(fù)后的AOF文件,并進(jìn)行數(shù)據(jù)恢復(fù)。
aof-use-rdb-preamble yes
AOF文件時(shí),Redis能夠在AOF文件中使用RDB前導(dǎo),以加快重寫(xiě)和恢復(fù)速度。啟用此選項(xiàng)后,重寫(xiě)的AOF文件由兩個(gè)不同的節(jié)組成:RDB file、AOF tailRedis時(shí),會(huì)識(shí)別AOF文件以Redis字符串開(kāi)頭,并加載帶前綴的RDB文件,然后繼續(xù)加載AOF尾部。理論
優(yōu)點(diǎn)
數(shù)據(jù)的完整性和一致性更高, AOF的持久化通過(guò)使用不同的策略,最多丟失1秒的數(shù)據(jù);AOF文件是一個(gè)只進(jìn)行追加的日志文件,不需要寫(xiě)入seek;Redis可以在AOF文件體積變得過(guò)大時(shí),自動(dòng)地在后臺(tái)對(duì)AOF進(jìn)行重寫(xiě),重寫(xiě)操作是絕對(duì)安全的;AOF文件記錄的寫(xiě)入操作以Redis協(xié)議的格式保存,容易讀懂,容易對(duì)文件進(jìn)行分析;
缺點(diǎn)
對(duì)于相同的數(shù)據(jù)集來(lái)說(shuō), AOF文件的體積通常要大于RDB文件的體積;根據(jù)所使用的 fsync策略,AOF的速度可能會(huì)慢于RDB。
在一般情況下,每秒 fsync的性能依然非常高,而關(guān)閉fsync可以讓AOF的速度和RDB一樣快, 即使在高負(fù)荷之下也是如此。不過(guò)在處理巨大的寫(xiě)入載入時(shí),RDB可以提供更有保證的最大延遲時(shí)間(latency)。
對(duì)比與總結(jié)
如何選擇使用哪種持久化方式?
PostgreSQL 的數(shù)據(jù)安全性,應(yīng)該同時(shí)使用兩種持久化功能。RDB 持久化。AOF是目前主流的持久化方式。AOF持久化,但我們并不推薦這種方式:因?yàn)槎〞r(shí)生成 RDB 快照(snapshot)非常便于進(jìn)行數(shù)據(jù)庫(kù)備份,并且 RDB 恢復(fù)數(shù)據(jù)集的速度也要比 AOF 恢復(fù)的速度要快。AOF和RDB之間的相互作用
2.4 的 Redis 中,BGSAVE 執(zhí)行的過(guò)程中,不可以執(zhí)行 BGREWRITEAOF 。反過(guò)來(lái)說(shuō),在 BGREWRITEAOF 執(zhí)行的過(guò)程中,也不可以執(zhí)行 BGSAVE。這可以防止兩個(gè) Redis 后臺(tái)進(jìn)程同時(shí)對(duì)磁盤(pán)進(jìn)行大量的I/O 操作。BGSAVE 正在執(zhí)行,并且用戶(hù)顯示地調(diào)用 BGREWRITEAOF 命令,那么服務(wù)器將向用戶(hù)回復(fù)一個(gè) OK 狀態(tài), 并告知用戶(hù)BGREWRITEAOF 已經(jīng)被預(yù)定執(zhí)行:一旦 BGSAVE 執(zhí)行完畢,BGREWRITEAOF就會(huì)正式開(kāi)始。Redis 啟動(dòng)時(shí),如果 RDB持久化和 AOF 持久化都被打開(kāi)了, 那么程序會(huì)優(yōu)先使用 AOF 文件來(lái)恢復(fù)數(shù)據(jù)集,因?yàn)?nbsp;AOF文件所保存的數(shù)據(jù)通常是最完整的。備份redis數(shù)據(jù)
創(chuàng)建一個(gè)定期任務(wù)( cron job),每小時(shí)將一個(gè)RDB文件備份到一個(gè)文件夾,并且每天將一個(gè)RDB文件備份到另一個(gè)文件夾;確??煺盏膫浞荻紟в邢鄳?yīng)的日期和時(shí)間信息,每次執(zhí)行定期任務(wù)腳本時(shí),使用 find命令來(lái)刪除過(guò)期的快照;至少每天一次,將 RDB備份到你的數(shù)據(jù)中心之外,或者至少是備份到你運(yùn)行Redis服務(wù)器的物理機(jī)器之外。
性能建議
slave上持久化RDB文件,而且只需要15分鐘備份一次就夠了,只保留save 900 1這條規(guī)則。AOF,好處是在最?lèi)毫忧闆r下也只會(huì)丟失不超過(guò)2秒數(shù)據(jù),啟動(dòng)腳本較簡(jiǎn)單只load自己的AOF文件就可以了。代價(jià)一是帶來(lái)了持續(xù)的IO,二是AOF rewrite的最后將rewrite過(guò)程中產(chǎn)生的新數(shù)據(jù)寫(xiě)到新文件造成的阻塞幾乎是不可避免的。AOF rewrite的頻率,AOF重寫(xiě)的基礎(chǔ)大小默認(rèn)值64M太小了,可以設(shè)置到5G以上。默認(rèn)超過(guò)原大小的100%時(shí)重寫(xiě)可以改到適當(dāng)?shù)臄?shù)值。AOF,僅靠Master-Slave Replication實(shí)現(xiàn)高可用性也可以。能省掉一大筆IO,也減少了rewrite時(shí)帶來(lái)的系統(tǒng)波動(dòng)。代價(jià)是如果Master/Slave同時(shí)倒掉,會(huì)丟失十幾分鐘的數(shù)據(jù),啟動(dòng)腳本也要比較兩個(gè)Master/Slave中的RDB文件,載入較新的那個(gè)。
推薦閱讀

迄今為止程序員寫(xiě)過(guò)的最大Bug:虧損30億、致6人死亡,甚至差點(diǎn)毀滅世界

某程序員自述:我,三十多歲,逃離北上廣,通過(guò)技術(shù)移民到加拿大!

某程序員吐槽同事:剛畢業(yè)的妹子讓他幫忙查代碼,他卻把妹子懟哭了,活該單身!
END


頂級(jí)程序員:topcoding
做最好的程序員社區(qū):Java后端開(kāi)發(fā)、Python、大數(shù)據(jù)、AI
一鍵三連「分享」、「點(diǎn)贊」和「在看」
評(píng)論
圖片
表情
