1. 程式人生 > >redis持久化的兩種方式

redis持久化的兩種方式

第一條 客戶端 效率 推薦 利用 每次 破壞 高可用性 程序

Redis的所有數據都是保存在內存中,然後不定期的通過異步方式保存到磁盤上(這稱為“半持久化模式”);也可以把每一次數據變化都寫入到一個append only file(aof)裏面(這稱為“全持久化模式”)。

由於Redis的數據都存放在內存中,如果沒有配置持久化,redis重啟後數據就全丟失了,於是需要開啟redis的持久化功能,將數據保存到磁盤上,當redis重啟後,可以從磁盤中恢復數據。redis提供兩種方式進行持久化,一種是RDB持久化(原理是將Reids在內存中的數據庫記錄定時dump到磁盤上的RDB持久化),另外一種是AOF(append only file)持久化(原理是將Reids的操作日誌以追加的方式寫入文件)。那麽這兩種持久化方式有什麽區別呢,改如何選擇呢?網上看了大多數都是介紹這兩種方式怎麽配置,怎麽使用,就是沒有介紹二者的區別,在什麽應用場景下使用。

2、二者的區別

RDB持久化是指在指定的時間間隔內將內存中的數據集快照寫入磁盤,實際操作過程是fork一個子進程,先將數據集寫入臨時文件,寫入成功後,再替換之前的文件,用二進制壓縮存儲。

技術分享圖片

AOF持久化以日誌的形式記錄服務器所處理的每一個寫、刪除操作,查詢操作不會記錄,以文本的方式記錄,可以打開文件看到詳細的操作記錄。

技術分享圖片

3、二者優缺點

RDB存在哪些優勢呢?

1). 一旦采用該方式,那麽你的整個Redis數據庫將只包含一個文件,這對於文件備份而言是非常完美的。比如,你可能打算每個小時歸檔一次最近24小時的數據,同時還要每天歸檔一次最近30天的數據。通過這樣的備份策略,一旦系統出現災難性故障,我們可以非常容易的進行恢復。

2). 對於災難恢復而言,RDB是非常不錯的選擇。因為我們可以非常輕松的將一個單獨的文件壓縮後再轉移到其它存儲介質上。

3). 性能最大化。對於Redis的服務進程而言,在開始持久化時,它唯一需要做的只是fork出子進程,之後再由子進程完成這些持久化的工作,這樣就可以極大的避免服務進程執行IO操作了。

4). 相比於AOF機制,如果數據集很大,RDB的啟動效率會更高。

RDB又存在哪些劣勢呢?

1). 如果你想保證數據的高可用性,即最大限度的避免數據丟失,那麽RDB將不是一個很好的選擇。因為系統一旦在定時持久化之前出現宕機現象,此前沒有來得及寫入磁盤的數據都將丟失。

2). 由於RDB是通過fork子進程來協助完成數據持久化工作的,因此,如果當數據集較大時,可能會導致整個服務器停止服務幾百毫秒,甚至是1秒鐘。

AOF的優勢有哪些呢?

1). 該機制可以帶來更高的數據安全性,即數據持久性。Redis中提供了3中同步策略,即每秒同步、每修改同步和不同步。事實上,每秒同步也是異步完成的,其效率也是非常高的,所差的是一旦系統出現宕機現象,那麽這一秒鐘之內修改的數據將會丟失。而每修改同步,我們可以將其視為同步持久化,即每次發生的數據變化都會被立即記錄到磁盤中。可以預見,這種方式在效率上是最低的。至於無同步,無需多言,我想大家都能正確的理解它。

2). 由於該機制對日誌文件的寫入操作采用的是append模式,因此在寫入過程中即使出現宕機現象,也不會破壞日誌文件中已經存在的內容。然而如果我們本次操作只是寫入了一半數據就出現了系統崩潰問題,不用擔心,在Redis下一次啟動之前,我們可以通過redis-check-aof工具來幫助我們解決數據一致性的問題。

3). 如果日誌過大,Redis可以自動啟用rewrite機制。即Redis以append模式不斷的將修改數據寫入到老的磁盤文件中,同時Redis還會創建一個新的文件用於記錄此期間有哪些修改命令被執行。因此在進行rewrite切換時可以更好的保證數據安全性。

4). AOF包含一個格式清晰、易於理解的日誌文件用於記錄所有的修改操作。事實上,我們也可以通過該文件完成數據的重建。

AOF的劣勢有哪些呢?

1). 對於相同數量的數據集而言,AOF文件通常要大於RDB文件。RDB 在恢復大數據集時的速度比 AOF 的恢復速度要快。

2). 根據同步策略的不同,AOF在運行效率上往往會慢於RDB。總之,每秒同步策略的效率是比較高的,同步禁用策略的效率和RDB一樣高效。

RDB 和 AOF ,我應該用哪一個?
一般來說,如果想達到足以媲美 PostgreSQL 的數據安全性, 你應該同時使用兩種持久化功能。如果你非常關心你的數據,但仍然可以承受數分鐘以內的數據丟失, 那麽你可以只使用 RDB 持久化。有很多用戶都只使用 AOF 持久化, 但我們並不推薦這種方式: 因為定時生成 RDB 快照(snapshot)非常便於進行數據庫備份, 並且 RDB 恢復數據集的速度也要比 AOF 恢復的速度要快, 除此之外, 使用 RDB 還可以避免之前提到的 AOF 程序的 bug 。因為以上提到的種種原因, 未來我們可能會將 AOF 和 RDB 整合成單個持久化模型。 (這是一個長期計劃。)

二者選擇的標準,就是看系統是願意犧牲一些性能,換取更高的緩存一致性(aof),還是願意寫操作頻繁的時候,不啟用備份來換取更高的性能,待手動運行save的時候,再做備份(rdb)。rdb這個就更有些 eventually consistent的意思了。

RDB 快照:
在默認情況下, Redis 將數據庫快照保存在名字為 dump.rdb 的二進制文件中。你可以對 Redis 進行設置, 讓它在“ N 秒內數據集至少有 M 個改動”這一條件被滿足時, 自動保存一次數據集。你也可以通過調用 SAVE 或者 BGSAVE , 手動讓 Redis 進行數據集保存操作。比如說, 以下設置會讓 Redis 在滿足“ 60 秒內有至少有 1000 個鍵被改動”這一條件時, 自動保存一次數據集:
save 60 1000
這種持久化方式被稱為快照(snapshot)。

快照的運作方式:
當 Redis 需要保存 dump.rdb 文件時, 服務器執行以下操作:
Redis 調用 fork() ,同時擁有父進程和子進程。
子進程將數據集寫入到一個臨時 RDB 文件中。
當子進程完成對新 RDB 文件的寫入時,Redis 用新 RDB 文件替換原來的 RDB 文件,並刪除舊的 RDB 文件。
這種工作方式使得 Redis 可以從寫時復制(copy-on-write)機制中獲益。
只進行追加操作的文件(append-only file,AOF)
快照功能並不是非常耐久(durable): 如果 Redis 因為某些原因而造成故障停機, 那麽服務器將丟失最近寫入、且仍未保存到快照中的那些數據。盡管對於某些程序來說, 數據的耐久性並不是最重要的考慮因素, 但是對於那些追求完全耐久能力(full durability)的程序來說, 快照功能就不太適用了。
從 1.1 版本開始, Redis 增加了一種完全耐久的持久化方式: AOF 持久化。
你可以通過修改配置文件來打開 AOF 功能:
appendonly yes
從現在開始, 每當 Redis 執行一個改變數據集的命令時(比如 SET), 這個命令就會被追加到 AOF 文件的末尾。
這樣的話, 當 Redis 重新啟時, 程序就可以通過重新執行 AOF 文件中的命令來達到重建數據集的目的。

AOF 重寫:
因為 AOF 的運作方式是不斷地將命令追加到文件的末尾, 所以隨著寫入命令的不斷增加, AOF 文件的體積也會變得越來越大。舉個例子, 如果你對一個計數器調用了 100 次 INCR , 那麽僅僅是為了保存這個計數器的當前值, AOF 文件就需要使用 100 條記錄(entry)。然而在實際上, 只使用一條 SET 命令已經足以保存計數器的當前值了, 其余 99 條記錄實際上都是多余的。為了處理這種情況, Redis 支持一種有趣的特性: 可以在不打斷服務客戶端的情況下, 對 AOF 文件進行重建(rebuild)。執行 BGREWRITEAOF 命令, Redis 將生成一個新的 AOF 文件, 這個文件包含重建當前數據集所需的最少命令。

AOF 有多耐久?
你可以配置 Redis 多久才將數據 fsync 到磁盤一次。
有三個選項:
每次有新命令追加到 AOF 文件時就執行一次 fsync :非常慢,也非常安全。
每秒 fsync 一次:足夠快(和使用 RDB 持久化差不多),並且在故障時只會丟失 1 秒鐘的數據。
從不 fsync :將數據交給操作系統來處理。更快,也更不安全的選擇。
推薦(並且也是默認)的措施為每秒 fsync 一次, 這種 fsync 策略可以兼顧速度和安全性。
總是 fsync 的策略在實際使用中非常慢, 即使在 Redis 2.0 對相關的程序進行了改進之後仍是如此 —— 頻繁調用 fsync 註定了這種策略不可能快得起來。

如果 AOF 文件出錯了,怎麽辦?
服務器可能在程序正在對 AOF 文件進行寫入時停機, 如果停機造成了 AOF 文件出錯(corrupt), 那麽 Redis 在重啟時會拒絕載入這個 AOF 文件, 從而確保數據的一致性不會被破壞。


當發生這種情況時, 可以用以下方法來修復出錯的 AOF 文件:
為現有的 AOF 文件創建一個備份。
使用 Redis 附帶的 redis-check-aof 程序,對原來的 AOF 文件進行修復。
$ redis-check-aof --fix
(可選)使用 diff -u 對比修復後的 AOF 文件和原始 AOF 文件的備份,查看兩個文件之間的不同之處。
重啟 Redis 服務器,等待服務器載入修復後的 AOF 文件,並進行數據恢復。
AOF 的運作方式
AOF 重寫和 RDB 創建快照一樣,都巧妙地利用了寫時復制機制。

以下是 AOF 重寫的執行步驟:
Redis 執行 fork() ,現在同時擁有父進程和子進程。
子進程開始將新 AOF 文件的內容寫入到臨時文件。對於所有新執行的寫入命令,父進程一邊將它們累積到一個內存緩存中,一邊將這些改動追加到現有 AOF 文件的末尾: 這樣即使在重寫的中途發生停機,現有的 AOF 文件也還是安全的。當子進程完成重寫工作時,它給父進程發送一個信號,父進程在接收到信號之後,將內存緩存中的所有數據追加到新 AOF 文件的末尾。現在 Redis 原子地用新文件替換舊文件,之後所有命令都會直接追加到新 AOF 文件的末尾。

為最新的 dump.rdb 文件創建一個備份。
將備份放到一個安全的地方。
執行以下兩條命令:
redis-cli> CONFIG SET appendonly yes
redis-cli> CONFIG SET save ""
確保命令執行之後,數據庫的鍵的數量沒有改變。
確保寫命令會被正確地追加到 AOF 文件的末尾。
步驟 3 執行的第一條命令開啟了 AOF 功能: Redis 會阻塞直到初始 AOF 文件創建完成為止, 之後 Redis 會繼續處理命令請求, 並開始將寫入命令追加到 AOF 文件末尾。
步驟 3 執行的第二條命令用於關閉 RDB 功能。 這一步是可選的, 如果你願意的話, 也可以同時使用 RDB 和 AOF 這兩種持久化功能。
別忘了在 redis.conf 中打開 AOF 功能! 否則的話, 服務器重啟之後, 之前通過 CONFIG SET 設置的配置就會被遺忘, 程序會按原來的配置來啟動服務器。

RDB 和 AOF 之間的相互作用:
在版本號大於等於 2.4 的 Redis 中, BGSAVE 執行的過程中, 不可以執行 BGREWRITEAOF 。 反過來說, 在 BGREWRITEAOF 執行的過程中, 也不可以執行 BGSAVE 。
這可以防止兩個 Redis 後臺進程同時對磁盤進行大量的 I/O 操作。
如果 BGSAVE 正在執行, 並且用戶顯示地調用 BGREWRITEAOF 命令, 那麽服務器將向用戶回復一個 OK 狀態, 並告知用戶, BGREWRITEAOF 已經被預定執行: 一旦 BGSAVE 執行完畢, BGREWRITEAOF 就會正式開始。當 Redis 啟動時, 如果 RDB 持久化和 AOF 持久化都被打開了, 那麽程序會優先使用 AOF 文件來恢復數據集, 因為 AOF 文件所保存的數據通常是最完整的。

備份 Redis 數據:
Redis 對於數據備份是非常友好的, 因為你可以在服務器運行的時候對 RDB 文件進行復制: RDB 文件一旦被創建, 就不會進行任何修改。 當服務器要創建一個新的 RDB 文件時, 它先將文件的內容保存在一個臨時文件裏面, 當臨時文件寫入完畢時, 程序才使用 原子地用臨時文件替換原來的 RDB 文件。這也就是說, 無論何時, 復制 RDB 文件都是絕對安全的。

4、常用配置

RDB持久化配置

Redis會將數據集的快照dump到dump.rdb文件中。此外,我們也可以通過配置文件來修改Redis服務器dump快照的頻率,在打開6379.conf文件之後,我們搜索save,可以看到下面的配置信息:

save 900 1 #在900秒(15分鐘)之後,如果至少有1個key發生變化,則dump內存快照。

save 300 10 #在300秒(5分鐘)之後,如果至少有10個key發生變化,則dump內存快照。

save 60 10000 #在60秒(1分鐘)之後,如果至少有10000個key發生變化,則dump內存快照。

AOF持久化配置

在Redis的配置文件中存在三種同步方式,它們分別是:

appendfsync always #每次有數據修改發生時都會寫入AOF文件。

appendfsync everysec #每秒鐘同步一次,該策略為AOF的缺省策略。

appendfsync no #從不同步。高效但是數據不會被持久化。

redis持久化的兩種方式