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