redis 簡單整理——持久化之AOF[二十]
前言
簡單介紹一下AOF。
正文
AOF(append only file)持久化:以獨立日誌的方式記錄每次寫命令, 重啟時再重新執行AOF檔案中的命令達到恢復資料的目的。
AOF的主要作用 是解決了資料持久化的實時性,目前已經是Redis持久化的主流方式。理解 掌握好AOF持久化機制對我們兼顧資料安全性和效能非常有幫助。
開啟AOF功能需要設定配置:appendonly yes,預設不開啟。AOF檔名 通過appendfilename配置設定,預設檔名是appendonly.aof。儲存路徑同 RDB持久化方式一致,通過dir配置指定。AOF的工作流程操作:命令寫入 (append)、檔案同步(sync)、檔案重寫(rewrite)、重啟載入 (load)。
那麼這裡我要改成yes。
1)所有的寫入命令會追加到aof_buf(緩衝區)中。
2)AOF緩衝區根據對應的策略向硬碟做同步操作。
3)隨著AOF檔案越來越大,需要定期對AOF檔案進行重寫,達到壓縮 的目的。
4)當Redis伺服器重啟時,可以載入AOF檔案進行資料恢復。
寫入命令
AOF命令寫入的內容直接是文字協議格式。例如set hello world這條命 令,在AOF緩衝區會追加如下文字
*3\r\n$3\r\nset\r\n$5\r\nhello\r\n$5\r\nworld\r\n
1)AOF為什麼直接採用文字協議格式?可能的理由如下:
文字協議具有很好的相容性。
開啟AOF後,所有寫入命令都包含追加操作,直接採用協議格式,避 免了二次處理開銷。
文字協議具有可讀性,方便直接修改和處理。
2)AOF為什麼把命令追加到aof_buf中?
Redis使用單執行緒響應命令,如 果每次寫AOF檔案命令都直接追加到硬碟,那麼效能完全取決於當前硬碟負載。
先寫入緩衝區aof_buf中,還有另一個好處,Redis可以提供多種緩衝區 同步硬碟的策略,在效能和安全性方面做出平衡。
檔案同步
Redis提供了多種AOF緩衝區同步檔案策略,由引數appendfsync控制, 不同值的含義如下表。
系統呼叫write和fsync說明:
·write操作會觸發延遲寫(delayed write)機制。Linux在核心提供頁緩 衝區用來提高硬碟IO效能。write操作在寫入系統緩衝區後直接返回。同步 硬碟操作依賴於系統排程機制,例如:緩衝區頁空間寫滿或達到特定時間周 期。同步檔案之前,如果此時系統故障宕機,緩衝區內資料將丟失。
·fsync針對單個檔案操作(比如AOF檔案),做強制硬碟同步,fsync將 阻塞直到寫入硬碟完成後返回,保證了資料持久化。
配置為always時,每次寫入都要同步AOF檔案,在一般的SATA硬碟 上,Redis只能支援大約幾百TPS寫入,顯然跟Redis高效能特性背道而馳, 不建議配置
·配置為no,由於作業系統每次同步AOF檔案的週期不可控,而且會加 大每次同步硬碟的資料量,雖然提升了效能,但資料安全性無法保證。 ·配置為everysec,是建議的同步策略,也是預設配置,做到兼顧效能和 資料安全性。理論上只有在系統突然宕機的情況下丟失1秒的資料。
重寫機制
隨著命令不斷寫入AOF,檔案會越來越大,為了解決這個問題,Redis 引入AOF重寫機制壓縮檔案體積。AOF檔案重寫是把Redis程序內的資料轉 化為寫命令同步到新AOF檔案的過程。
重寫後的AOF檔案為什麼可以變小?有如下原因:
1)程序內已經超時的資料不再寫入檔案。
2)舊的AOF檔案含有無效命令,如del key1、hdel key2、srem keys、set a111、set a222等。重寫使用程序內資料直接生成,這樣新的AOF檔案只保 留最終資料的寫入命令。
3)多條寫命令可以合併為一個,如:lpush list a、lpush list b、lpush list c可以轉化為:lpush list a b c。為了防止單條命令過大造成客戶端緩衝區溢 出,對於list、set、hash、zset等型別操作,以64個元素為界拆分為多條。
AOF重寫降低了檔案佔用空間,除此之外,另一個目的是:更小的AOF 檔案可以更快地被Redis載入。
AOF重寫過程可以手動觸發和自動觸發:
·手動觸發:直接呼叫bgrewriteaof命令。
我這裡寫入一個命令set hello world 然後 set hello good.
然後手動觸發:
就變成了壓縮態,裡面存有redis的版本。
這樣看不清楚,然後我再次寫入set hello world:
可以看到紅框中就是壓縮狀態。
·自動觸發:根據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-min- size&&(aof_current_size-aof_base_size)/aof_base_size>=auto-aof-rewrite- percentage
其中aof_current_size和aof_base_size可以在info Persistence統計資訊中檢視。
壓縮過程:
1)執行AOF重寫請求。
如果當前程序正在執行AOF重寫,請求不執行並返回如下響應:
ERR Background append only file rewriting already in progress
如果當前程序正在執行bgsave操作,重寫命令延遲到bgsave完成之後再 執行,返回如下響應:
Background append only file rewriting scheduled
2)父程序執行fork建立子程序,開銷等同於bgsave過程。
3.1)主程序fork操作完成後,繼續響應其他命令。所有修改命令依然寫 入AOF緩衝區並根據appendfsync策略同步到硬碟,保證原有AOF機制正確性
3.2)由於fork操作運用寫時複製技術,子程序只能共享fork操作時的內 存資料。由於父程序依然響應命令,Redis使用“AOF重寫緩衝區”儲存這部 分新資料,防止新AOF檔案生成期間丟失這部分資料
4)子程序根據記憶體快照,按照命令合併規則寫入到新的AOF檔案。每 次批量寫入硬碟資料量由配置aof-rewrite-incremental-fsync控制,預設為 32MB,防止單次刷盤資料過多造成硬碟阻塞。
5.1)新AOF檔案寫入完成後,子程序傳送訊號給父程序,父程序更新 統計資訊,具體見info persistence下的aof_*相關統計。
5.2)父程序把AOF重寫緩衝區的資料寫入到新的AOF檔案。
5.3)使用新AOF檔案替換老檔案,完成AOF重寫。
過載過程
AOF和RDB檔案都可以用於伺服器重啟時的資料恢復。
1)AOF持久化開啟且存在AOF檔案時,優先載入AOF檔案,列印如下 日誌:
* DB loaded from append only file: 5.841 seconds
2)AOF關閉或者AOF檔案不存在時,載入RDB檔案,列印如下日誌:
* DB loaded from disk: 5.586 seconds
3)載入AOF/RDB檔案成功後,Redis啟動成功
4)AOF/RDB檔案存在錯誤時,Redis啟動失敗並列印錯誤資訊。
檔案校驗
載入損壞的AOF檔案時會拒絕啟動,並列印如下日誌:
# Bad file format reading the append only file: make a backup of your AOF file, then use ./redis-check-aof --fix <filename>
對於錯誤格式的AOF檔案,先進行備份,然後採用redis-check-aof--fix命 令進行修復,修復後使用diff-u對比資料的差異,找出丟失的資料,有些可以人工修改補全。
AOF檔案可能存在結尾不完整的情況,比如機器突然掉電導致AOF尾部 檔案命令寫入不全。Redis為我們提供了aof-load-truncated配置來相容這種情 況,預設開啟。載入AOF時,當遇到此問題時會忽略並繼續啟動,同時列印 如下警告日誌:
# !!! Warning: short read while loading the AOF file !!! # !!! Truncating the AOF at offset 397856725 !!! # AOF loaded anyway because aof-load-truncated is enabled
結
下一節介紹永續性的問題定位和優化。