本文將簡單介紹redis持久化的兩種方式
redis提供了兩種不同級別的持久化方式:
- RDB持久化方式能夠在指定的時(shí)間間隔能對你的數(shù)據(jù)進(jìn)行快照存儲.
- AOF持久化方式記錄每次對服務(wù)器寫的操作,當(dāng)服務(wù)器重啟的時(shí)候會重新執(zhí)行這些命令來恢復(fù)原始的數(shù)據(jù),AOF命令以redis協(xié)議追加保存每次寫的操作到文件末尾.Redis還能對AOF文件進(jìn)行后臺重寫,使得AOF文件的體積不至于過大.
在簡單了解了以上兩種持久化方式的不同點(diǎn)后,我們開始一個(gè)一個(gè)的進(jìn)行了解窗轩。
RDB持久化:
RDB方式的優(yōu)缺點(diǎn):
優(yōu)點(diǎn):
- RDB是一個(gè)非常緊湊的文件,它保存了某個(gè)時(shí)間點(diǎn)得數(shù)據(jù)集,非常適用于數(shù)據(jù)集的備份。比如你可以在每個(gè)小時(shí)報(bào)保存一下過去24小時(shí)內(nèi)的數(shù)據(jù),同時(shí)每天保存過去30天的數(shù)據(jù),這樣即使出了問題你也可以根據(jù)需求恢復(fù)到不同版本的數(shù)據(jù)集仓洼。
- RDB是一個(gè)緊湊的單一文件,很方便傳送到另一個(gè)遠(yuǎn)端數(shù)據(jù)中心色建,非常適用于災(zāi)難恢復(fù)。
- RDB在保存RDB文件時(shí)父進(jìn)程唯一需要做的就是fork出一個(gè)子進(jìn)程,接下來的工作全部由子進(jìn)程來做箕戳,父進(jìn)程不需要再做其他IO操作,所以RDB持久化方式可以最大化redis的性能.
- 與AOF相比,在恢復(fù)大的數(shù)據(jù)集的時(shí)候玻墅,RDB方式會更快一些.
通過以上RDB持久化的工作方式澳厢,我們也可以很快的感覺到它的一些缺點(diǎn)
缺點(diǎn):
- 如果redis意外停止工作,你希望丟失最少的數(shù)據(jù)剩拢,那么RDB很明顯就不合適了徐伐,因?yàn)樗菚r(shí)間段的進(jìn)行持久化的搬素,哪怕你是五分鐘持久化一次也難免會丟失幾分鐘的數(shù)據(jù)。
- RDB 需要經(jīng)常fork子進(jìn)程來保存數(shù)據(jù)集到硬盤上,當(dāng)數(shù)據(jù)集比較大的時(shí)候,fork的過程是非常耗時(shí)的,可能會導(dǎo)致Redis在一些毫秒級內(nèi)不能響應(yīng)客戶端的請求.如果數(shù)據(jù)集巨大并且CPU性能不是很好的情況下,這種情況會持續(xù)1秒摸屠。
RDB持久化觸發(fā)方式:
1季二、手動觸發(fā)
主要有兩種方式:save命令以及bgsava命令
save命令阻塞當(dāng)前Redis服務(wù)器揭措,知道RDB過程完成為止胯舷,對于內(nèi)存比較大的實(shí)例會造成長時(shí)間阻塞桑嘶,線上環(huán)境不建議使用
bgsave命令Redis進(jìn)程執(zhí)行fork操作創(chuàng)建子進(jìn)程逃顶,RDB持久化過程由子進(jìn)程負(fù)責(zé)充甚,完成后自動結(jié)束伴找。阻塞只發(fā)生在fork階段,時(shí)間很短
因此在使用中我們基本上使用bgsave的方式進(jìn)行RDB技矮,其工作流程主要為:
- Redis父進(jìn)程判斷當(dāng)前是否存在正在執(zhí)行的子進(jìn)程,如果有則直接返回
- 如果沒有則父進(jìn)程執(zhí)行fork操作新建一個(gè)子進(jìn)程,在fork的過程中父進(jìn)程會短暫阻塞寸五,創(chuàng)建子進(jìn)程成功,則解除父進(jìn)程的阻塞韧拒,子進(jìn)程進(jìn)行后續(xù)的持久化操作叛溢。
- 進(jìn)程創(chuàng)建RDB文件,根據(jù)父進(jìn)程內(nèi)存生成臨時(shí)快照文件楷掉,完成后對原有文件進(jìn)行原子替換
- 進(jìn)程發(fā)送信號給父進(jìn)程衣示完成烹植,父進(jìn)程更新統(tǒng)計(jì)信息
在項(xiàng)目中我們?nèi)绻褂肦DB持久化方式草雕,我們根據(jù)項(xiàng)目實(shí)際需求來執(zhí)行多長時(shí)間去持久化固以,既調(diào)用以下方法
jedis.bgsave();
2、自動觸發(fā)
在redis.windows.conf配置文件中我們打開可以看到默認(rèn)的觸發(fā)機(jī)制诫钓,如sava 60 10000 表示如果60秒內(nèi)有1000個(gè)鍵被改變則進(jìn)行持久化操作
save 900 1
save 300 10
save 60 10000
RDB文件處理
在redis.windows.conf配置文件中我們通過查看dbfilename以及dir可以看到RDB文件的名字以及存儲路徑菌湃,在redis重啟啟動時(shí)如果沒有配置AOF持久化方式那么就會讀取dump.rdb文件慢味,如果rdb文件損壞,則可以使用redis-check-dump進(jìn)行修復(fù)或油,再重新加載。
AOF持久化:
AOF方式優(yōu)點(diǎn)
- 使用AOF 會讓你的Redis更加耐久: 你可以使用不同的fsync策略:無fsync,每秒fsync,每次寫的時(shí)候fsync.使用默認(rèn)的每秒fsync策略,Redis的性能依然很好(fsync是由后臺線程進(jìn)行處理的,主線程會盡力處理客戶端請求),一旦出現(xiàn)故障顶岸,你最多丟失1秒的數(shù)據(jù).
- AOF文件是一個(gè)只進(jìn)行追加的日志文件,所以不需要寫入seek,即使由于某些原因(磁盤空間已滿,寫的過程中宕機(jī)等等)未執(zhí)行完整的寫入命令,你也也可使用redis-check-aof工具修復(fù)這些問題.
- Redis 可以在 AOF 文件體積變得過大時(shí)霹抛,自動地在后臺對 AOF 進(jìn)行重寫: 重寫后的新 AOF 文件包含了恢復(fù)當(dāng)前數(shù)據(jù)集所需的最小命令集合杯拐。 整個(gè)重寫操作是絕對安全的端逼,因?yàn)?Redis 在創(chuàng)建新 AOF 文件的過程中顶滩,會繼續(xù)將命令追加到現(xiàn)有的 AOF 文件里面,即使重寫過程中發(fā)生停機(jī)礁鲁,現(xiàn)有的 AOF 文件也不會丟失仅醇。 而一旦新 AOF 文件創(chuàng)建完畢着憨,Redis 就會從舊 AOF 文件切換到新 AOF 文件,并開始對新 AOF 文件進(jìn)行追加操作甲抖。
- AOF 文件有序地保存了對數(shù)據(jù)庫執(zhí)行的所有寫入操作漆改, 這些寫入操作以 Redis 協(xié)議的格式保存, 因此 AOF 文件的內(nèi)容非常容易被人讀懂准谚, 對文件進(jìn)行分析(parse)也很輕松挫剑。 導(dǎo)出(export) AOF 文件也非常簡單: 舉個(gè)例子, 如果你不小心執(zhí)行了 FLUSHALL 命令柱衔, 但只要 AOF 文件未被重寫樊破, 那么只要停止服務(wù)器, 移除 AOF 文件末尾的 FLUSHALL 命令唆铐, 并重啟 Redis 哲戚, 就可以將數(shù)據(jù)集恢復(fù)到 FLUSHALL 執(zhí)行之前的狀態(tài)。
AOF方式缺點(diǎn)
- 對于相同的數(shù)據(jù)集來說艾岂,AOF 文件的體積通常要大于 RDB 文件的體積顺少。
- 根據(jù)所使用的 fsync 策略,AOF 的速度可能會慢于 RDB 。 在一般情況下脆炎, 每秒 fsync 的性能依然非常高袱蚓, 而關(guān)閉 fsync 可以讓 AOF 的速度和 RDB 一樣快, 即使在高負(fù)荷之下也是如此响蓉。 不過在處理巨大的寫入載入時(shí)枫甲,RDB 可以提供更有保證的最大延遲時(shí)間(latency)。
使用方式:
使用前我們需要配置:appendonly yes 開啟AOF脏毯,默認(rèn)時(shí)不開啟的,文件名則是通過appendfilename 設(shè)置吉嫩,路徑則和RDB一致。
在我們執(zhí)行set方法時(shí)忙迁,:
如下:
set fd 222
會對應(yīng)的在appendonly.aof中生成對應(yīng)的命令
*2 $6 SELECT $1 0 *3 $3 set $2 fd $3 222
然后會按照我們所配的aof同步策略進(jìn)行同步硬盤,在redis重啟的時(shí)候會加載AOF文件進(jìn)行數(shù)據(jù)恢復(fù)
同步策略
Redis提供了多種AOF緩沖區(qū)同步文件策略,由參數(shù)appendfsync控制
- 配置為always時(shí)删豺,每次寫入都要同步AOF文
- 配置為no,Redis不會主動調(diào)用fsync去將AOF日志內(nèi)容同步到磁盤,由操作系統(tǒng)自動調(diào)度刷磁盤
- 當(dāng)設(shè)置appendfsync為everysec的時(shí)候,Redis會默認(rèn)每隔一秒進(jìn)行一次fsync調(diào)用蓬蝶,將緩沖區(qū)中的數(shù)據(jù)寫到磁盤
日志重寫
因?yàn)?AOF 的運(yùn)作方式是不斷地將命令追加到文件的末尾著摔, 所以隨著寫入命令的不斷增加禾锤, AOF 文件的體積也會變得越來越大。舉個(gè)例子黄娘, 如果你對一個(gè)計(jì)數(shù)器調(diào)用了 100 次 INCR , 那么僅僅是為了保存這個(gè)計(jì)數(shù)器的當(dāng)前值氮凝, AOF 文件就需要使用 100 條記錄(entry)罩阵。然而在實(shí)際上, 只使用一條 SET 命令已經(jīng)足以保存計(jì)數(shù)器的當(dāng)前值了傅是, 其余 99 條記錄實(shí)際上都是多余的帽驯。
為了處理這種情況, Redis 支持一種有趣的特性: 可以在不打斷服務(wù)客戶端的情況下嫌术, 對 AOF 文件進(jìn)行重建(rebuild)。執(zhí)行 BGREWRITEAOF 命令, Redis 將生成一個(gè)新的 AOF 文件择示, 這個(gè)文件包含重建當(dāng)前數(shù)據(jù)集所需的最少命令。Redis 2.2 需要自己手動執(zhí)行 BGREWRITEAOF 命令谈秫; Redis 2.4 則可以自動觸發(fā) AOF 重寫
//java重寫命令
jedis.bgrewriteaof();
原理:
- Redis 執(zhí)行 fork() 迄本,現(xiàn)在同時(shí)擁有父進(jìn)程和子進(jìn)程置媳。
- 子進(jìn)程開始將新 AOF 文件的內(nèi)容寫入到臨時(shí)文件。
- 對于所有新執(zhí)行的寫入命令路捧,父進(jìn)程一邊將它們累積到一個(gè)內(nèi)存緩存中,一邊將這些改動追加到現(xiàn)有 AOF 文件的末尾,這樣樣即使在重寫的中途發(fā)生停機(jī)涉波,現(xiàn)有的 AOF 文件也還是安全的惭聂。
- 當(dāng)子進(jìn)程完成重寫工作時(shí),它給父進(jìn)程發(fā)送一個(gè)信號,父進(jìn)程在接收到信號之后,將內(nèi)存緩存中的所有數(shù)據(jù)追加到新 AOF 文件的末尾狼纬。
- 搞定!現(xiàn)在 Redis 原子地用新文件替換舊文件,之后所有命令都會直接追加到新 AOF 文件的末尾柠贤。
注:RDB和AOF的具體使用還是看業(yè)務(wù)的具體需求,可單獨(dú)使用也可搭配使用
當(dāng) Redis 啟動時(shí)镜盯, 如果 RDB 持久化和 AOF 持久化都被打開了恩闻, 那么程序會優(yōu)先使用 AOF 文件來恢復(fù)數(shù)據(jù)集, 因?yàn)?AOF 文件所保存的數(shù)據(jù)通常是最完整的。