1. 程式人生 > >進階的Redis之資料持久化RDB與AOF

進階的Redis之資料持久化RDB與AOF

大家都知道,Redis之所以效能好,讀寫快,是因為Redis是一個記憶體資料庫,它的操作都幾乎基於記憶體。但是記憶體型資料庫有一個很大的弊端,就是當資料庫程序崩潰或系統重啟的時候,如果記憶體資料不儲存的話,裡面的資料就會丟失不見了。這樣的資料庫並不是一個可靠的資料庫。

所以資料的持久化是記憶體型資料庫的重中之重。它不僅提供資料儲存硬碟的功能,還可以藉此用硬碟容量擴充套件資料儲存空間,使得Redis的可以儲存超過機器本身記憶體大小的資料。

Redis對於資料持久化提供了兩種持久化的方案,RDB與AOF。它們的原理和使用場景都大不相同,下面我們來詳細地瞭解下。

RDB——資料快照(Snapshot)

RDB,提供一個某個時間點的資料的Snapshot,儲存在RDB檔案中。它可以通過SAVE/BGSAVE命令手動執行,把資料Snapshot寫到RDB檔案,也可以通過配置,定時執行。

Redis也可以通過載入RDB檔案,把資料從磁碟載入讀取到Redis中。

RDB檔案建立

連上Redis,設值一些值,然後執行SAVE命令。

然後可以檢視下redis.conf的持久化工作目錄。進入目錄可以看到儲存了一個dump.rdb檔案。該檔案是一個二進位制檔案,無法直接正常開啟。

至於SAVE/BGSAVE的區別,就是前置是阻塞執行,此時服務不會接受請求,後者是Fork一個子程序出來,由該程序去執行儲存RDB檔案的操作,不影響使用者請求。

P.S. Redis是單程序的,所以BGSAVE只能Fork一個子程序,而不是建立一個執行緒處理。

以上是手動執行的過程。但在生產我們很少會手動登上服務去執行操作,所以更多的時候是依賴Redis的配置,定時儲存RDB檔案。

開啟redis.conf配置檔案,找到SNAPSHOTTING的配置,Save Point的設定。

圖中的配置意思是,當至少有一個key變更時,900秒後會執行一次SAVE。其他配置同理,有10次變更,300秒後儲存一次.....

在Redis中,這個自動儲存RDB的功能是預設開啟的。

RDB檔案載入

先kill掉Redis程序,再重新啟動Redis Server,會發現日誌會有這樣的一行,

並且Redis中,依然有之前設定的三個值。說明Redis在啟動的時候,會載入資料初始化。

不過,這裡載入的初始化資料不一定是RDB的。如果Redis開啟了AOF,會優先從AOF初始化資料,否則才會載入RDB的資料。

RDB優缺點

優點:

  1. RDB是某一時間點的快照,是一個緊湊的單檔案,更多用於資料備份。可以按每小時或每日來備份,方便從不同的版本恢復資料。
  2. 單檔案容易傳輸到遠端服務做故障恢復。
  3. RDB可以Fork子程序進行持久化,使Redis可以更好地處理使用者請求
  4. 在大量資料的情況下,RDB相比較於AOF會更快的載入。

缺點:

  1. 如果Redis不及時儲存RDB檔案,會造成資料的丟失。例如系統突然斷電,但未來得及儲存資料。即使你設定更多的Save point,也無法保證100%的資料不丟失。
  2. RDB經常需要fork子程序去執行,但如果再大量資料的情況下,這個fork操作會非常耗CPU資源的。對比AOF雖然也是fork,但是它的資料儲存處理是可以控制的,不需要全量儲存。

AOF——日誌追加(Append-Only)

Redis的另外一種持久化方案就是AOF,Append Only File。AOF相當於一個操作的日誌記錄,每次對於資料的變更都會記錄追加到AOF日誌。當服務啟動的時候就會讀這些操作日誌,重新執行一次操作,從而恢復原始資料。

AOF啟用

AOF預設是關閉的。開啟redis.conf配置檔案,找到appendonly no改成appendonly yes

AOF和RDB是可以共存的,只要儲存的檔名不衝突。

AOF fsync同步規則

配置檔案往下拉,看到fsync的配置。

fsync()是一個系統呼叫函式,告訴作業系統把資料寫到硬碟上,而不是快取更多資料才寫到硬碟。這樣的呼叫可以及時儲存資料到硬碟上。

Redis提供了三種fsync的呼叫方式

  • appendfsync always,每次操作記錄都同步到硬碟上,最低效,最安全。
  • appendfsync everysec,每秒執行一次把操作記錄同步到硬碟上。預設選項。
  • appendfsync no,不執行fysnc呼叫,讓作業系統自動操作把快取資料寫到硬碟上,不可靠,但最快。

AOF檔案格式解析

開啟AOF後,會再工作目錄看到appendonly.aof檔案。

在客戶端上執行一些命令後,開啟AOF檔案,可以觀察到有對應的操作的記錄日誌。
檔案解析說明:

  • *,表示命令的引數個數,例如set a 1是三個引數,所以是*3
  • $,表示引數的位元組數,例如set這個引數是三位元組,所以是$3,key值a是一個位元組,所以是$1
  • 無符號,表示是引數的資料,例如set,a,1就是具體的資料

日誌重寫

AOF雖然比RDB更可靠,但缺點也是比較明顯的,就是每次寫操作都要把操作日誌寫到檔案上,這樣會導致檔案非常冗餘。

假若你要自增一個計數器100次,如果不重寫,AOF檔案就就會有這100次的自增記錄,如INCR a。如果執行了日誌重寫,那麼檔案只會保留set a 100而不是100條INCR a。這樣擁有相同的結果,但可以大大減少AOF的檔案大小,並且可以讓AOF載入的時候提升載入的效率。

看回redis.conf配置,有兩項控制rewrite的選項。

  • auto-aof-rewrite-percentage 100,當檔案增長100%(一倍)時候,自動重寫。
  • auto-aof-rewrite-min-size 64mb,日誌重寫最小檔案大小,如果小於該大小,不會自動重寫。

來實驗一下重寫的結果,我們先設定一個a值,然後自增多次,檢視AOF檔案內容。裡面有很多INCR的語句記錄

然後我們手動執行下BGREWRITEOF,執行日誌重寫。

可以看到,多個incr語句,變成了一個 set a 6語句,減少了5個 incr a語句的操作日誌。

AOF優缺點

優點:

  1. AOF可以設定 完全不同步、每秒同步、每次操作同,預設是每秒同步。因為AOF是操作指令的追加,所以可以頻繁的大量的同步。
  2. AOF檔案是一個值追加日誌的檔案,即使服務宕機為寫入完整的命令,也可以通過redis-check-aof工具修復這些問題。
  3. 如果AOF檔案過大,Redis會在後臺自動地重寫AOF檔案。重寫後會使AOF檔案壓縮到最小所需的指令集。
  4. AOF檔案是有序儲存資料庫的所有寫入操作,易讀,易分析。即使如果不小心誤操作資料庫,也很容易找出錯誤指令,恢復到某個資料節點。例如不小心FLUSHALL,可以非常容易恢復到執行命令之前。

缺點

  1. 相同資料量下,AOF的檔案通常體積會比RDB大。因為AOF是存指令的,而RDB是所有指令的結果快照。但AOF在日誌重寫後會壓縮一些空間。
  2. 在大量寫入和載入的時候,AOF的效率會比RDB低。因為大量寫入,AOF會執行更多的儲存命令,載入的時候也需要大量的重執行命令來得到最後的結果。RDB對此更有優勢。

如何選擇

以上已經基本瞭解過RDB和AOF的使用、基本原理以及對應的優缺點。那麼在實際當中,我們到底怎麼去選擇用哪種持久化方式呢?

一般來說,不考慮硬碟大小,最安全的做法是RDB與AOF同時使用,即使AOF損壞無法修復,還可以用RDB來恢復資料。

如果Redis的資料在你的服務中並不是必要的資料,例如只是當簡單的快取,沒有快取也不會造成快取雪崩。說明資料的安全可靠性並不是首要考慮範圍內,那麼單獨只使用RDB就可以了。

不推薦單獨使用AOF,因為AOF對於資料的恢復載入來說,比RDB慢。並且Redis官方也說明了,AOF有一個罕見的bug。出了問題無法很好的解決。所以使用AOF的時候,最好還是有RDB作為資料備份。

根據官方的意願描述,在未來可能會有一種RDB與AOF相結合的持久化模型。到時Redis持久化就不再如此麻煩費勁了,我們拭目以待吧。

更多技術文章、精彩乾貨,請關注
部落格:zackku.com
微信公眾號:Zack說碼