Redis持久化RDB和AOF的實現
什麼是持久化?
持久化(Persistence),即把資料(如記憶體中的物件)儲存到可永久儲存的儲存裝置中(如磁碟)。持久化的主要應用是將記憶體中的物件儲存在資料庫中,或者儲存在磁碟檔案中、XML資料檔案中等等。
還可以從如下兩個層面簡單的理解持久化 :
- 應用層:如果關閉(shutdown)你的應用然後重新啟動則先前的資料依然存在。
- 系統層:如果關閉(shutdown)你的系統(電腦)然後重新啟動則先前的資料依然存在。
Redis為什麼要持久化?
Redis是記憶體資料庫,為了保證效率所有的操作都是在記憶體中完成。資料都是快取在記憶體中,當你重啟系統或者關閉系統,之前快取在記憶體中的資料都會丟失再也不能找回。因此為了避免這種情況,Redis需要實現持久化將記憶體中的資料儲存起來。
Redis官方提供了不同級別的持久化方式:
- RDB持久化:能夠在指定的時間間隔能對你的資料進行快照儲存。
- AOF持久化:記錄每次對伺服器寫的操作,當伺服器重啟的時候會重新執行這些命令來恢復原始的資料,AOF命令以redis協議追加儲存每次寫的操作到檔案末尾。Redis還能對AOF檔案進行後臺重寫,使得AOF檔案的體積不至於過大。
- 不使用持久化:如果你只希望你的資料在伺服器執行的時候存在,你也可以選擇不使用任何持久化方式。
- 同時開啟RDB和AOF:你也可以同時開啟兩種持久化方式,在這種情況下當redis重啟的時候會優先載入AOF檔案來恢復原始的資料,因為在通常情況下AOF檔案儲存的資料集要比RDB檔案儲存的資料集要完整。
這麼多持久化方式我們應該怎麼選?在選擇之前我們需要搞清楚每種持久化方式的區別以及各自的優劣勢。
RDB持久化
RDB(Redis Database)持久化是把當前記憶體資料生成快照儲存到硬碟的過程,觸發RDB持久化過程分為手動觸發和自動觸發。
手動觸發
手動觸發對應save命令,會阻塞當前Redis伺服器,直到RDB過程完成為止,對於記憶體比較大的例項會造成長時間阻塞,線上環境不建議使用。
自動觸發
自動觸發對應bgsave命令,Redis程序執行fork操作建立子程序,RDB持久化過程由子程序負責,完成後自動結束。阻塞只發生在fork階段,一般時間很短。
在redis.conf配置檔案中可以配置:save <seconds> <changes>
表示xx秒內資料修改xx次時自動觸發bgsave。 如果想關閉自動觸發,可以在save命令後面加一個空串,即:
save ""
還有其他常見可以觸發bgsave,如:
- 如果從節點執行全量複製操作,主節點自動執行bgsave生成RDB檔案併發送給從節點。
- 預設情況下執行shutdown命令時,如果沒有開啟AOF持久化功能則 自動執行bgsave。
bgsave工作機制
(1)執行bgsave命令,Redis父程序判斷當前是否存在正在執行的子程序,如RDB/AOF子程序,如果存在,bgsave命令直接返回。
(2)父程序執行fork操作建立子程序,fork操作過程中父程序會阻塞,通 過info stats命令檢視latest_fork_usec選項,可以獲取最近一個fork操作的耗時,單位為微秒
(3)父程序fork完成後,bgsave命令返回“Background saving started”資訊並不再阻塞父程序,可以繼續響應其他命令。
(4)子程序建立RDB檔案,根據父程序記憶體生成臨時快照檔案,完成後對原有檔案進行原子替換。執行lastsave命令可以獲取最後一次生成RDB的 時間,對應info統計的rdb_last_save_time選項。
(5)程序傳送訊號給父程序表示完成,父程序更新統計資訊,具體見 info Persistence下的rdb_*相關選項。
-- RDB持久化完 --
AOF持久化
AOF(append only file)持久化:以獨立日誌的方式記錄每次寫命令, 重啟時再重新執行AOF檔案中的命令達到恢復資料的目的。AOF的主要作用是解決了資料持久化的實時性,目前已經是Redis持久化的主流方式。
AOF持久化工作機制
開啟AOF功能需要配置:appendonly yes,預設不開啟。
AOF檔名 通過appendfilename配置設定,預設檔名是appendonly.aof。儲存路徑同 RDB持久化方式一致,通過dir配置指定。
AOF的工作流程操作:命令寫入 (append)、檔案同步(sync)、檔案重寫(rewrite)、重啟載入 (load)。
(1)所有的寫入命令會追加到aof_buf(緩衝區)中。
(2)AOF緩衝區根據對應的策略向硬碟做同步操作。
AOF為什麼把命令追加到aof_buf中?Redis使用單執行緒響應命令,如果每次寫AOF檔案命令都直接追加到硬碟,那麼效能完全取決於當前硬碟負載。先寫入緩衝區aof_buf中,還有另一個好處,Redis可以提供多種緩衝區同步硬碟的策略,在效能和安全性方面做出平衡。
(3)隨著AOF檔案越來越大,需要定期對AOF檔案進行重寫,達到壓縮的目的。
(4)當Redis伺服器重啟時,可以載入AOF檔案進行資料恢復。
AOF重寫(rewrite)機制
重寫的目的:
- 減小AOF檔案佔用空間;
- 更小的AOF 檔案可以更快地被Redis載入恢復。
AOF重寫可以分為手動觸發和自動觸發:
- 手動觸發:直接呼叫bgrewriteaof命令。
- 自動觸發:根據auto-aof-rewrite-min-size和auto-aof-rewrite-percentage引數確定自動觸發時機。
auto-aof-rewrite-min-size:表示執行AOF重寫時檔案最小體積,預設 為64MB。
auto-aof-rewrite-percentage:代表當前AOF檔案空間 (aof_current_size)和上一次重寫後AOF檔案空間(aof_base_size)的比值。
自動觸發時機
當aof_current_size>auto-aof-rewrite-minsize 並且(aof_current_size-aof_base_size)/aof_base_size>=auto-aof-rewritepercentage。
其中aof_current_size和aof_base_size可以在info Persistence統計資訊中檢視。
資料恢復流程說明:
(1)AOF持久化開啟且存在AOF檔案時,優先載入AOF檔案。
(2)AOF關閉或者AOF檔案不存在時,載入RDB檔案。
(3)載入AOF/RDB檔案成功後,Redis啟動成功。
(4)AOF/RDB檔案存在錯誤時,Redis啟動失敗並列印錯誤資訊。
-- AOF持久化完 --
AOF檔案重寫後為什麼會變小?
(1)舊的AOF檔案含有無效的命令,如:del key1, hdel key2等。重寫只保留最終資料的寫入命令。
(2)多條命令可以合併,如lpush list a,lpush list b,lpush list c可以直接轉化為lpush list a b c。
RDB和AOF的優缺點
RDB優點
- RDB 是一個非常緊湊的檔案,它儲存了某個時間點的資料集,非常適用於資料集的備份,比如你可以在每個小時報儲存一下過去24小時內的資料,同時每天儲存過去30天的資料,這樣即使出了問題你也可以根據需求恢復到不同版本的資料集。
- RDB 是一個緊湊的單一檔案,很方便傳送到另一個遠端資料中心,非常適用於災難恢復。
- RDB 在儲存 RDB 檔案時父程序唯一需要做的就是 fork 出一個子程序,接下來的工作全部由子程序來做,父程序不需要再做其他 IO 操作,所以 RDB 持久化方式可以最大化 Redis 的效能。
- 與AOF相比,在恢復大的資料集的時候,RDB 方式會更快一些。
AOF優點
- 你可以使用不同的 fsync 策略:無 fsync、每秒 fsync 、每次寫的時候 fsync .使用預設的每秒 fsync 策略, Redis 的效能依然很好( fsync 是由後臺執行緒進行處理的,主執行緒會盡力處理客戶端請求),一旦出現故障,你最多丟失1秒的資料。
- AOF檔案是一個只進行追加的日誌檔案,所以不需要寫入seek,即使由於某些原因(磁碟空間已滿,寫的過程中宕機等等)未執行完整的寫入命令,你也也可使用redis-check-aof工具修復這些問題。
- Redis 可以在 AOF 檔案體積變得過大時,自動地在後臺對 AOF 進行重寫: 重寫後的新 AOF 檔案包含了恢復當前資料集所需的最小命令集合。 整個重寫操作是絕對安全的,因為 Redis 在建立新 AOF 檔案的過程中,會繼續將命令追加到現有的 AOF 檔案裡面,即使重寫過程中發生停機,現有的 AOF 檔案也不會丟失。 而一旦新 AOF 檔案建立完畢,Redis 就會從舊 AOF 檔案切換到新 AOF 檔案,並開始對新 AOF 檔案進行追加操作。
- AOF 檔案有序地儲存了對資料庫執行的所有寫入操作, 這些寫入操作以 Redis 協議的格式儲存, 因此 AOF 檔案的內容非常容易被人讀懂, 對檔案進行分析(parse)也很輕鬆。 匯出(export) AOF 檔案也非常簡單: 舉個例子, 如果你不小心執行了 FLUSHALL 命令, 但只要 AOF 檔案未被重寫, 那麼只要停止伺服器, 移除 AOF 檔案末尾的 FLUSHALL 命令, 並重啟 Redis , 就可以將資料集恢復到 FLUSHALL 執行之前的狀態。
RDB缺點
- Redis 要完整的儲存整個資料集是一個比較繁重的工作,你通常會每隔5分鐘或者更久做一次完整的儲存,萬一在 Redis 意外宕機,你可能會丟失幾分鐘的資料。
- RDB 需要經常 fork 子程序來儲存資料集到硬碟上,當資料集比較大的時候, fork 的過程是非常耗時的,可能會導致 Redis 在一些毫秒級內不能響應客戶端的請求。
AOF缺點
- 對於相同的資料集來說,AOF 檔案的體積通常要大於 RDB 檔案的體積。
- 資料恢復(load)時AOF比RDB慢,通常RDB 可以提供更有保證的最大延遲時間。
RDB和AOF簡單對比總結
RDB優點:
- RDB 是緊湊的二進位制檔案,比較適合備份,全量複製等場景
- RDB 恢復資料遠快於 AOF
RDB缺點:
- RDB 無法實現實時或者秒級持久化;
- 新老版本無法相容 RDB 格式。
AOF優點:
- 可以更好地保護資料不丟失;
- appen-only 模式寫入效能比較高;
- 適合做災難性的誤刪除緊急恢復。
AOF缺點:
- 對於同一份檔案,AOF 檔案要比 RDB 快照大;
- AOF 開啟後,會對寫的 QPS 有所影響,相對於 RDB 來說 寫 QPS 要下降;
- 資料庫恢復比較慢, 不合適做冷備。
redis 內部使用檔案事件處理器 file event handler,這個檔案事件處理器是單執行緒的,所以 redis 才叫做單執行緒的模型。它採用 IO 多路複用機制同時監聽多個 socket,根據 socket 上的事件來選擇對應的事件處理器進行處理。
redis 單執行緒模型也能效率這麼高?
- 純記憶體操作
- 核心是基於非阻塞的 IO 多路複用機制
- 單執行緒反而避免了多執行緒的頻繁上下文切換問題