【Redis学习】Redis持久化
1、RDB
1.1 工作原理
Redis調(diào)用fork(),產(chǎn)生一個子進程。
子進程把數(shù)據(jù)寫到一個臨時的RDB文件。
當(dāng)子進程寫完新的RDB文件后,把舊的RDB文件替換掉。
1.2 優(yōu)點
RDB文件是一個很簡潔的單文件,它保存了某個時間點的Redis數(shù)據(jù),很適合用于做備份。你可以設(shè)定一個時間點對RDB文件進行歸檔,這樣就能在需要的時候很輕易的把數(shù)據(jù)恢復(fù)到不同的版本。
基于上面所描述的特性,RDB很適合用于災(zāi)備。單文件很方便就能傳輸?shù)竭h(yuǎn)程的服務(wù)器上。
RDB的性能很好,需要進行持久化時,主進程會fork一個子進程出來,然后把持久化的工作交給子進程,自己不會有相關(guān)的I/O操作。
比起AOF,在數(shù)據(jù)量比較大的情況下,RDB的啟動速度更快。
1.3 缺點
RDB容易造成數(shù)據(jù)的丟失。假設(shè)每5分鐘保存一次快照,如果Redis因為某些原因不能正常工作,那么從上次產(chǎn)生快照到Redis出現(xiàn)問題這段時間的數(shù)據(jù)就會丟失了。
RDB使用fork()產(chǎn)生子進程進行數(shù)據(jù)的持久化,如果數(shù)據(jù)比較大的話可能就會花費點時間,造成Redis停止服務(wù)幾毫秒。如果數(shù)據(jù)量很大且CPU性能不是很好的時候,停止服務(wù)的時間甚至?xí)?秒。
1.4 文件路徑和名稱
默認(rèn)Redis會把快照文件存儲為當(dāng)前目錄下一個名為dump.rdb的文件。要修改文件的存儲路徑和名稱,可以通過修改配置文件redis.conf實現(xiàn):
# RDB文件名,默認(rèn)為dump.rdb。 dbfilename dump.rdb# 文件存放的目錄,AOF文件同樣存放在此目錄下。默認(rèn)為當(dāng)前工作目錄。 dir ./1.5 保存點(RDB的啟用和禁用)
你可以配置保存點,使Redis如果在每N秒后數(shù)據(jù)發(fā)生了M次改變就保存快照文件。例如下面這個保存點配置表示每60秒,如果數(shù)據(jù)發(fā)生了1000次以上的變動,Redis就會自動保存快照文件:
save 60 1000 保存點可以設(shè)置多個,Redis的配置文件就默認(rèn)設(shè)置了3個保存點:# 格式為:save <seconds> <changes> # 可以設(shè)置多個。 save 900 1 #900秒后至少1個key有變動 save 300 10 #300秒后至少10個key有變動 save 60 10000 #60秒后至少10000個key有變動如果想禁用快照保存的功能,可以通過注釋掉所有”save”配置達到,或者在最后一條”save”配置后添加如下的配置:
save ""1.6 錯誤處理
默認(rèn)情況下,如果Redis在后臺生成快照的時候失敗,那么就會停止接收數(shù)據(jù),目的是讓用戶能知道數(shù)據(jù)沒有持久化成功。但是如果你有其他的方式可以監(jiān)控到Redis及其持久化的狀態(tài),那么可以把這個功能禁止掉。
stop-writes-on-bgsave-error yes1.7 數(shù)據(jù)壓縮
默認(rèn)Redis會采用LZF對數(shù)據(jù)進行壓縮。如果你想節(jié)省點CPU的性能,你可以把壓縮功能禁用掉,但是數(shù)據(jù)集就會比沒壓縮的時候要打。
rdbcompression yes1.8 數(shù)據(jù)校驗
從版本5的RDB的開始,一個CRC64的校驗碼會放在文件的末尾。這樣更能保證文件的完整性,但是在保存或者加載文件時會損失一定的性能(大概10%)。如果想追求更高的性能,可以把它禁用掉,這樣文件在寫入校驗碼時會用0替代,加載的時候看到0就會直接跳過校驗。
rdbchecksum yes1.9 RDB 快照
在默認(rèn)情況下, Redis 將數(shù)據(jù)庫快照保存在名字為 dump.rdb 的二進制文件中。
你可以對 Redis 進行設(shè)置, 讓它在“ N 秒內(nèi)數(shù)據(jù)集至少有 M 個改動”這一條件被滿足時, 自動保存一次數(shù)據(jù)集。
Redis提供了兩個命令用于手動生成快照。你也可以通過調(diào)用它們,手動讓Redis進行數(shù)據(jù)集保存操作。
SAVE
SAVE命令會使用同步的方式生成RDB快照文件,這意味著在這個過程中會阻塞所有其他客戶端的請求。因此不建議在生產(chǎn)環(huán)境使用這個命令,除非因為某種原因需要去阻止Redis使用子進程進行后臺生成快照(例如調(diào)用fork(2)出錯)。
BGSAVE
BGSAVE命令使用后臺的方式保存RDB文件,調(diào)用此命令后,會立刻返回OK返回碼。Redis會產(chǎn)生一個子進程進行處理并立刻恢復(fù)對客戶端的服務(wù)。在客戶端我們可以使用LASTSAVE命令查看操作是否成功。
127.0.0.1:6379> BGSAVE
Background saving started
127.0.0.1:6379> LASTSAVE
(integer) 1433936394
配置文件里禁用了快照生成功能不影響SAVE和BGSAVE命令的效果。
1.10 快照的運作方式
當(dāng) Redis 需要保存 dump.rdb 文件時, 服務(wù)器執(zhí)行以下操作:
Redis 調(diào)用 fork() ,同時擁有父進程和子進程。
子進程將數(shù)據(jù)集寫入到一個臨時 RDB 文件中。
當(dāng)子進程完成對新 RDB 文件的寫入時,Redis 用新 RDB 文件替換原來的 RDB 文件,并刪除舊的 RDB 文件。
這種工作方式使得 Redis 可以從寫時復(fù)制(copy-on-write)機制中獲益。
2、AOF
快照并不是很可靠。如果你的電腦突然宕機了,或者電源斷了,又或者不小心殺掉了進程,那么最新的數(shù)據(jù)就會丟失。而AOF文件則提供了一種更為可靠的持久化方式。每當(dāng)Redis接受到會修改數(shù)據(jù)集的命令時,就會把命令追加到AOF文件里,當(dāng)你重啟Redis時,AOF里的命令會被重新執(zhí)行一次,重建數(shù)據(jù)。
2.1 優(yōu)點
比RDB可靠。你可以制定不同的fsync策略:不進行fsync、每秒fsync一次和每次查詢進行fsync。默認(rèn)是每秒fsync一次。這意味著你最多丟失一秒鐘的數(shù)據(jù)。
AOF日志文件是一個純追加的文件。就算是遇到突然停電的情況,也不會出現(xiàn)日志的定位或者損壞問題。甚至如果因為某些原因(例如磁盤滿了)命令只寫了一半到日志文件里,我們也可以用redis-check-aof這個工具很簡單的進行修復(fù)。
當(dāng)AOF文件太大時,Redis會自動在后臺進行重寫。重寫很安全,因為重寫是在一個新的文件上進行,同時Redis會繼續(xù)往舊的文件追加數(shù)據(jù)。新文件上會寫入能重建當(dāng)前數(shù)據(jù)集的最小操作命令的集合。當(dāng)新文件重寫完,Redis會把新舊文件進行切換,然后開始把數(shù)據(jù)寫到新文件上。
AOF把操作命令以簡單易懂的格式一條接一條的保存在文件里,很容易導(dǎo)出來用于恢復(fù)數(shù)據(jù)。例如我們不小心用FLUSHALL命令把所有數(shù)據(jù)刷掉了,只要文件沒有被重寫,我們可以把服務(wù)停掉,把最后那條命令刪掉,然后重啟服務(wù),這樣就能把被刷掉的數(shù)據(jù)恢復(fù)回來。
2.2 缺點
在相同的數(shù)據(jù)集下,AOF文件的大小一般會比RDB文件大。
在某些fsync策略下,AOF的速度會比RDB慢。通常fsync設(shè)置為每秒一次就能獲得比較高的性能,而在禁止fsync的情況下速度可以達到RDB的水平。
在過去曾經(jīng)發(fā)現(xiàn)一些很罕見的BUG導(dǎo)致使用AOF重建的數(shù)據(jù)跟原數(shù)據(jù)不一致的問題。
2.3 啟用AOF
把配置項appendonly設(shè)為yes:appendonly yes 文件路徑和名稱# 文件存放目錄,與RDB共用。默認(rèn)為當(dāng)前工作目錄。 dir ./# 默認(rèn)文件名為appendonly.aof appendfilename "appendonly.aof"2.4 可靠性
你可以配置Redis調(diào)用fsync的頻率,有三個選項:
1.每當(dāng)有新命令追加到AOF的時候調(diào)用fsync。速度最慢,但是最安全。
2.每秒fsync一次。速度快(2.4版本跟快照方式速度差不多),安全性不錯(最多丟失1秒的數(shù)據(jù))。
3.從不fsync,交由系統(tǒng)去處理。這個方式速度最快,但是安全性一般。
推薦使用每秒fsync一次的方式(默認(rèn)的方式),因為它速度快,安全性也不錯。相關(guān)配置如下:
// appendfsync always
appendfsync everysec
appendfsync no
2.5 AOF日志重寫
因為 AOF 的運作方式是不斷地將命令追加到文件的末尾, 所以隨著寫入命令的不斷增加, AOF 文件的體積也會變得越來越大。例如你遞增一個計數(shù)器100次,那么最終結(jié)果就是數(shù)據(jù)集里的計數(shù)器的值為最終的遞增結(jié)果,但是AOF文件里卻會把這100次操作完整的記錄下來。而事實上要恢復(fù)這個記錄,只需要1個命令就行了,也就是說AOF文件里那100條命令其實可以精簡為1條。所以Redis支持這樣一個功能:在不中斷服務(wù)的情況下在后臺重建AOF文件。
工作原理如下:
以下是 AOF 重寫的執(zhí)行步驟:
Redis 執(zhí)行 fork() ,現(xiàn)在同時擁有父進程和子進程。
子進程開始將新 AOF 文件的內(nèi)容寫入到臨時文件。
對于所有新執(zhí)行的寫入命令,父進程一邊將它們累積到一個內(nèi)存緩存中,一邊將這些改動追加到現(xiàn)有 AOF 文件的末尾: 這樣即使在重寫的中途發(fā)生停機,現(xiàn)有的 AOF 文件也還是安全的。
當(dāng)子進程完成重寫工作時,它給父進程發(fā)送一個信號,父進程在接收到信號之后,將內(nèi)存緩存中的所有數(shù)據(jù)追加到新 AOF 文件的末尾。
搞定!現(xiàn)在 Redis 原子地用新文件替換舊文件,之后所有命令都會直接追加到新 AOF 文件的末尾。
我們可以通過配置設(shè)置日志重寫的條件:
# Redis會記住自從上一次重寫后AOF文件的大小(如果自Redis啟動后還沒重寫過,則記住啟動時使用的AOF文件的大小)。 # 如果當(dāng)前的文件大小比起記住的那個大小超過指定的百分比,則會觸發(fā)重寫。 # 同時需要設(shè)置一個文件大小最小值,只有大于這個值文件才會重寫,以防文件很小,但是已經(jīng)達到百分比的情況。auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb 要禁用自動的日志重寫功能,我們可以把百分比設(shè)置為0:auto-aof-rewrite-percentage 0 Redis 2.4以上才可以自動進行日志重寫,之前的版本需要手動運行BGREWRITEAOF這個命令。2.6 數(shù)據(jù)損壞修復(fù)
服務(wù)器可能在程序正在對 AOF 文件進行寫入時停機, 如果停機造成了 AOF 文件出錯(corrupt), 那么 Redis 在重啟時會拒絕載入這個 AOF 文件, 從而確保數(shù)據(jù)的一致性不會被破壞。
當(dāng)發(fā)生這種情況時, 可以用以下方法來修復(fù)出錯的 AOF 文件:
1.為現(xiàn)有的 AOF 文件創(chuàng)建一個備份。
2.使用 Redis 附帶的 redis-check-aof 程序,對原來的 AOF 文件進行修復(fù)。
$ redis-check-aof –fix
(可選)使用 diff -u 對比修復(fù)后的 AOF 文件和原始 AOF 文件的備份,查看兩個文件之間的不同之處。
3.重啟 Redis 服務(wù)器,等待服務(wù)器載入修復(fù)后的 AOF 文件,并進行數(shù)據(jù)恢復(fù)。
3、 從RDB切換到AOF
這里只說Redis >= 2.2版本的方式:
備份一個最新的dump.rdb的文件,并把備份文件放在一個安全的地方。
運行以下兩條命令:
確保數(shù)據(jù)跟切換前一致。
確保數(shù)據(jù)正確的寫到AOF文件里。
第二條命令是用來禁用RDB的持久化方式,但是這不是必須的,因為你可以同時啟用兩種持久化方式。
記得對配置文件redis.conf進行編輯啟用AOF,因為命令行方式修改配置在重啟Redis后就會失效。
4、RDB 和 AOF ,我應(yīng)該用哪一個?
一般來說, 如果想達到足以媲美 PostgreSQL 的數(shù)據(jù)安全性, 你應(yīng)該同時使用兩種持久化功能。
如果你非常關(guān)心你的數(shù)據(jù), 但仍然可以承受數(shù)分鐘以內(nèi)的數(shù)據(jù)丟失, 那么你可以只使用 RDB 持久化。
有很多用戶都只使用 AOF 持久化, 但我們并不推薦這種方式: 因為定時生成 RDB 快照(snapshot)非常便于進行數(shù)據(jù)庫備份, 并且 RDB 恢復(fù)數(shù)據(jù)集的速度也要比 AOF 恢復(fù)的速度要快, 除此之外, 使用 RDB 還可以避免之前提到的 AOF 程序的 bug 。
因為以上提到的種種原因, 未來我們可能會將 AOF 和 RDB 整合成單個持久化模型。 (這是一個長期計劃。)
5、RDB 和 AOF 之間的相互作用
在版本號大于等于 2.4 的 Redis 中, BGSAVE 執(zhí)行的過程中, 不可以執(zhí)行 BGREWRITEAOF 。 反過來說, 在 BGREWRITEAOF 執(zhí)行的過程中, 也不可以執(zhí)行 BGSAVE 。
這可以防止兩個 Redis 后臺進程同時對磁盤進行大量的 I/O 操作。
如果 BGSAVE 正在執(zhí)行, 并且用戶顯示地調(diào)用 BGREWRITEAOF 命令, 那么服務(wù)器將向用戶回復(fù)一個 OK 狀態(tài), 并告知用戶, BGREWRITEAOF 已經(jīng)被預(yù)定執(zhí)行: 一旦 BGSAVE 執(zhí)行完畢, BGREWRITEAOF 就會正式開始。
當(dāng) Redis 啟動時, 如果 RDB 持久化和 AOF 持久化都被打開了, 那么程序會優(yōu)先使用 AOF 文件來恢復(fù)數(shù)據(jù)集, 因為 AOF 文件所保存的數(shù)據(jù)通常是最完整的。
6、備份 Redis 數(shù)據(jù)
先將下面這句話銘記于心: 一定要備份你的數(shù)據(jù)庫!
磁盤故障, 節(jié)點失效, 諸如此類的問題都可能讓你的數(shù)據(jù)消失不見, 不進行備份是非常危險的。
Redis 對于數(shù)據(jù)備份是非常友好的, 因為你可以在服務(wù)器運行的時候?qū)?RDB 文件進行復(fù)制: RDB 文件一旦被創(chuàng)建, 就不會進行任何修改。 當(dāng)服務(wù)器要創(chuàng)建一個新的 RDB 文件時, 它先將文件的內(nèi)容保存在一個臨時文件里面, 當(dāng)臨時文件寫入完畢時, 程序才使用 rename(2) 原子地用臨時文件替換原來的 RDB 文件。
這也就是說, 無論何時, 復(fù)制 RDB 文件都是絕對安全的。
建議的方法:
創(chuàng)建一個定期任務(wù)(cron job), 每小時將一個 RDB 文件備份到一個文件夾, 并且每天將一個 RDB 文件備份到另一個文件夾。
確保快照的備份都帶有相應(yīng)的日期和時間信息, 每次執(zhí)行定期任務(wù)腳本時, 使用 find 命令來刪除過期的快照: 比如說, 你可以保留最近 48 小時內(nèi)的每小時快照, 還可以保留最近一兩個月的每日快照。
至少每天一次, 將 RDB 備份到你的數(shù)據(jù)中心之外, 或者至少是備份到你運行 Redis 服務(wù)器的物理機器之外。
7、容災(zāi)備份
Redis 的容災(zāi)備份基本上就是對數(shù)據(jù)進行備份, 并將這些備份傳送到多個不同的外部數(shù)據(jù)中心。
容災(zāi)備份可以在 Redis 運行并產(chǎn)生快照的主數(shù)據(jù)中心發(fā)生嚴(yán)重的問題時, 仍然讓數(shù)據(jù)處于安全狀態(tài)。
因為很多 Redis 用戶都是創(chuàng)業(yè)者, 他們沒有大把大把的錢可以浪費, 所以下面介紹的都是一些實用又便宜的容債備份方法:
Amazon S3 ,以及其他類似 S3 的服務(wù),是一個構(gòu)建災(zāi)難備份系統(tǒng)的好地方。 最簡單的方法就是將你的每小時或者每日 RDB 備份加密并傳送到 S3 。 對數(shù)據(jù)的加密可以通過 gpg -c 命令來完成(對稱加密模式)。 記得把你的密碼放到幾個不同的、安全的地方去(比如你可以把密碼復(fù)制給你組織里最重要的人物)。 同時使用多個儲存服務(wù)來保存數(shù)據(jù)文件,可以提升數(shù)據(jù)的安全性。
傳送快照可以使用 SCP 來完成(SSH 的組件)。 以下是簡單并且安全的傳送方法: 買一個離你的數(shù)據(jù)中心非常遠(yuǎn)的 VPS , 裝上 SSH , 創(chuàng)建一個無口令的 SSH 客戶端 key , 并將這個 key 添加到 VPS 的 authorized_keys 文件中, 這樣就可以向這個 VPS 傳送快照備份文件了。 為了達到最好的數(shù)據(jù)安全性,至少要從兩個不同的提供商那里各購買一個 VPS 來進行數(shù)據(jù)容災(zāi)備份。
需要注意的是, 這類容災(zāi)系統(tǒng)如果沒有小心地進行處理的話, 是很容易失效的。
最低限度下, 你應(yīng)該在文件傳送完畢之后, 檢查所傳送備份文件的體積和原始快照文件的體積是否相同。 如果你使用的是 VPS , 那么還可以通過比對文件的 SHA1 校驗和來確認(rèn)文件是否傳送完整。
另外, 你還需要一個獨立的警報系統(tǒng), 讓它在負(fù)責(zé)傳送備份文件的傳送器(transfer)失靈時通知你。
總結(jié)
以上是生活随笔為你收集整理的【Redis学习】Redis持久化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Redis学习】Transaction
- 下一篇: Oracle数据库表空间占用过大的解决办