1. 程式人生 > >Redis 中的資料持久化策略(AOF)

Redis 中的資料持久化策略(AOF)

上一篇文章,我們講的是 Redis 的一種基於記憶體快照的持久化儲存策略 RDB,本質上他就是讓 redis fork 出一個子程序遍歷我們所有資料庫中的字典,進行磁碟檔案的寫入。

但其實這種方式是有缺點的,先不說阻塞式 save 呼叫會阻塞整個 redis 服務,即便非同步式 bgsave 也是基於時間間隔,每多少秒觸發了多少次更新操作才會生成 RDB 檔案,那麼如果某次 RDB 生成之後,緊接著服務宕機,就至少丟失幾秒甚至更多的資料,並且這些資料是無法挽回的。

而 AOF 是 redis 中的另一種資料持久化策略,它基於操作日誌,也是一個很優秀的持久化策略,當然也有缺點。那麼本篇就來講講這個 AOF 持久化策略。

一、什麼是 AOF 持久化策略

AOF 即 append only file,當 redis 採用這這種資料持久化策略的時候,每當 redis 伺服器收到一條更新命令時,操作結束之後會將這條命令新增到 aof 記憶體緩衝區,特定的時間下重新整理緩衝區到磁碟檔案中,也就是我們的 aof 檔案。

預設的 redis 啟動配置檔案中,會有這麼兩條配置:

appendonly 指定 redis 是否啟用 AOF 持久化策略,appendfilename 指明生成的 AOF 檔名稱。

你也可以將 appendonly 選項指定為 yes,然後執行一條 set 命令,看看 redis 根目錄下有沒有生成一個 appendonly.aof 檔案。

redis.conf 中還有 appendfsync 這麼一條配置,它指明 AOF 檔案的寫入頻率,即便 linux 中檔案 IO 使用的高效的 epoll,但每收到一條更新命令就進行一次檔案 IO,未免也太低效,況且也沒必要。

appendfsync 的配置項有以下三種值可選:

  • always:每一次系統 serverCorn 函式呼叫就重新整理一次快取區
  • everysec:每秒執行一次磁碟寫入,期間所有的命令都會儲存在 aof 快取區
  • no:不做控制,任由作業系統決定什麼時候重新整理緩衝區

redis 預設配置是 everysec,即每秒重新整理一次快取區。

二、AOF 重寫

所以,理論上來說,隨著 redis 伺服器執行時間的持續,生成的 aof 檔案只會越來越大,redis 提供 AOF 重寫策略幫助優化和壓縮 aof 檔案。

比如:

set a "a"
set b "b"
set c "c"
del a
del b

正常情況下,aof 檔案中會儲存著五條命令的 log,然後資料恢復的時候依次執行即可。而當你啟動 AOF 重寫後,實際上我們的 aof 檔案中只有 set c "c" 這一條命令的 log。

以上只是一個簡單的示例,實際上 AOF 重寫達到的效率比這優秀的多的多,往往能將幾百條甚至幾千條的命令日誌,重寫優化成個位數。帶給我們最直觀的好處就是,aof 檔案體積變小,資料恢復速度變快。

一般來說,我們可以通過向 redis 伺服器傳送 bgrewriteaof 命令觸發伺服器對 aof 檔案進行重寫,如果當前有正在執行的重寫子程序,則本次重寫 會推遲執行,否則,直接觸發一次重寫。

除此之外,我們還可以在配置檔案中配置 aof 檔案達到多大,自動觸發檔案重寫。

因為 aof 檔案重寫一樣是 fork 子程序並由子程序處理的,主程序依然提供服務,所以 redis 還提供一塊重寫緩衝區,當發現有子程序正在進行 aof 檔案重寫,最新的請求命令除了會新增到 AOF 緩衝區,還會新增進 AOF 重寫緩衝區,當子程序完成重寫任務後,主程序阻塞式將重寫緩衝區的命令日誌新增進最新的 aof 檔案中。

看幾條配置

no-appendfsync-on-rewrite 配置了當 redis 伺服器因為某些情況即將阻塞(例如 save)時是否需要將緩衝區中的 aof 命令寫入到磁碟,配置 yes 則每次遇到阻塞操作時重新整理快取到磁碟,配置為 no 則無需關心伺服器阻不阻塞,快取命令在快取區。

auto-aof-rewrite-percentage 配置了當 aof 檔案相較於上一版本的 aof 檔案大小的百分比達到多少時觸發 AOF 重寫。舉個例子,auto-aof-rewrite-percentage 選項配置為 100,上一版本的 aof 檔案大小為 100M,那麼當我們的 aof 檔案達到 200M 的時候,觸發 AOF 重寫。

auto-aof-rewite-min-size 配置了最小能容忍 aof 檔案大小,超過這個大小必須進行 AOF 重寫。

三、RDB 與 AOF

RDB 基於記憶體快照,有兩種方式 save 和 bgsave,前者會阻塞 redis 服務,後者是非同步 fork 子程序不影響主程序提供服務。大部分情況,我們會通過配置時間間隔觸發 RDB 檔案寫入。RDB 檔案中儲存的是 redis 記憶體中所有的資料一份快照。

優點是:

  1. 相同的資料量下,rdb 檔案要小於 aof 檔案,且恢復速度要快於 aof
  2. rdb 檔案中是整個資料的完整備份快照,資料儲存緊湊即便不同版本的 redis,也能順利恢復
  3. 整個 rdb 持久化,只需要 fork 一個子程序進行持久化即可,父程序依然可以提供服務,效率最大化

缺點是:

  1. 容易丟失資料,即便配置了事件時間觸發備份,也至少丟失一秒資料
  2. 如果資料量太大,fork 子程序的時候會阻塞毫秒級別時間

AOF 是基於命令操作日誌,每條更新命令都會被刷到快取區,然後在特定的時間節點被寫入 aof 磁碟檔案。

優點是:

  1. 相較於 RDB,AOF 資料可靠性更強,最多丟失一秒資料
  2. 資料庫容錯率變好,一些誤操作可以通過直接改 aof 檔案進行回退

缺點是:

  1. AOF 檔案通常較大且恢復效率比不上 RDB,不適合做資料冷備份

總的來說,AOF 策略會使資料穩定性更高,具有更完整的資料備份,RDB 恢復效率高適合做災難恢復,建議生產環境上兩者都開啟。

ps:Redis 官方號稱後續出一個新的持久化策略,整合 RDB 和 AOF 提供更高效率的資料持久化,期待中。