Redis-技術專區-幫從底層徹底吃透AOF技術原理


AOF持久化方式

AOF持久化方式是將redis的操作日志以追加的方式寫入磁盤文件中。AOF持久化是以日志的形式記錄服務器所處理的每一個寫、刪除操作,查詢操作不會記錄,以文本的方式記錄,可以打開文件看到詳細的操作記錄。

AOF實現方式

  • AOF(append only file)持久化是以獨立日志的方式記錄每次寫命令,重啟時再重新執行AOF文件中命令達到恢復數據的目的。
  • AOF的主要作用是解決了數據持久化的實時性,目前已經是Redis持久化的主流方式。

AOF優勢

  • 該機制可以帶來更高的數據安全性,即數據持久性。

  • Redis中提供了3中同步策略,即每秒同步、每修改同步和不同步

    • 每秒同步:事實上,每秒同步也是異步完成的,其效率也是非常高的,所差的是一旦系統出現宕機現象,那么這一秒鍾之內修改的數據將會丟失。

    • 每次修改:而每修改同步,我們可以將其視為同步持久化,即每次發生的數據變化都會被立即記錄到磁盤中。

    • 不同步:可以預見,這種方式在效率上是最低的。至於無同步,無需多言,我想大家都能正確的理解它。

  • 由於該機制對日志文件的寫入操作采用的是append模式,因此在寫入過程中即使出現宕機現象,也不會破壞日志文件中已經存在的內容

  • 如果我們本次操作只是寫入了一半數據就出現了系統崩潰問題,不用擔心,在Redis下一次啟動之前,我們可以通過redis-check-aof工具來幫助我們解決數據一致性的問題。

  • 如果日志過大,Redis可以自動啟用rewrite機制,壓縮和瘦身相關的aof文件。

    • Redis以append模式不斷的將修改數據寫入到老的磁盤文件中,同時Redis還會創建一個臨時的新文件用於記錄此期間有哪些修改命令被執行。

    • 因此在進行rewrite切換時可以更好的保證數據安全性。

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


AOF命令寫入

AOF命令寫入的內容直接是文本協議格式。AOF文件是純文本文件,其內容正是Redis客戶端向Redis發送的原始通信協議的內容。

例如:set hello world 這條命令,在AOF緩沖區會追加如下文本:

$3
set
$5
hello
$5
world
  • $3 : set指令的長度。set長度 == 3
  • set:代表着set指令
  • $5:hello key對應的值長度
  • hello:key值
  • $5:world value對應的值長度
  • world:value值

  1. AOF為什么直接采用文本協議格式?可能的理由如下:

    • 文本協議具有很好的兼容性。
       - 開啟AOF后,所有寫入命令都包含追加操作,直接采用協議格式,避免二次處理開銷。
    • 文本協議具有可讀性,方便直接修改和處理。
  2. AOF為什么把命令追加到aof_buf中?

    • Redis使用單線程響應命令,如果每次寫AOF文件命令都直接追加到硬盤,那么性能完全取決於當前硬盤負載。
    • 先寫入緩沖區aof_buf中,還有另一個好處,Redis可以提供多種緩沖區同步硬盤的策略,在性能和安全性方面做出平衡。

AOF配置

在redis的redis.conf配置文件中:

打開文件,找到 APPEND ONLY MODE 對應內容,默認情況下Redis沒有開啟AOF(append only file)方式的持久化,通過appendonly參數開啟

  1. AOF文件的保存位置和RDB文件的位置相同
都是通過dir參數設置的
dir /path
  1. redis 默認關閉,開啟需要手動把no改為yes
appendonly yes 
  1. 指定本地數據庫文件名,默認值為 appendonly.aof
appendfilename "appendonly.aof"

  1. Redis支持三種不同的刷寫模式,Redis提供了多種AOF緩沖區同步文件策略,由參數appendfsync控制:

    • 每次有數據修改發生時都寫入AOF文件中

      • 每次收到寫命令就立即強制寫入磁盤,是最有保證的完全的持久化,但速度也是最慢的,一般不推薦使用
      appendfsync always
      
      • 在一般的STAT硬盤上,Redis只能支持大約幾百TPS寫入,這是最安全也是最慢的方式,顯然跟Redis高性能特性背道而馳,不建議配置。
    • 每秒中同步一次,將過去一秒內發生的數據修改寫入AOF文件中

      • 每秒鍾強制寫入磁盤一次,在性能和持久化方面做了很好的折中,是受推薦的方式。
      appendfsync everysec
      
      • 是建議的同步策略,也是默認配置,做到兼顧性能和數據安全性,理論上只有在系統突然宕機的情況下丟失1s的數據。(嚴格來說最多丟失1s數據是不准確)
    • 不主動同步,高效但是數據不持久化,由操作系統來決定

      • 完全依賴OS的寫入,一般為30秒左右一次,性能最好但是持久化最沒有保證,不被推薦。
      appendfsync no
      
      • 由於操作系統每次同步AOF文件的周期,(即每30秒一次),而且會極大每次同步硬盤的數據量,雖然提升了性能,但數據安全性無法保證。

  1. Redis服務的AOF文件同步策略:

    • always (最安全但是最慢) :同步持久化,每次發生數據變化會立刻寫入到磁盤中。性能較差當數據完整性比較好(慢,安全)
    • everysec (默認的同步策略):出廠默認推薦,每秒異步記錄一次(默認值)
    • no (最快但是不安全):不同步
  2. 當進程中BGSAVE或BGREWRITEAOF命令正在執行時不阻止主進程中的fsync()調用(默認為no,當存在延遲問題時需調整為yes).

no-appendfsync-on-rewrite no

雖然每次執行更改數據庫內容的操作時,AOF都會將命令記錄在AOF文件中,但是事實上,由於操作系統的緩存機制,數據並沒有真正地寫入硬盤,而是進入了系統的硬盤緩存。在默認情況下系統每30秒會執行一次同步操作,以便將硬盤緩存中的內容真正地 寫入硬盤,在這30秒的過程中如果系統異常退出則會導致硬盤緩存中的數據丟失。一般來講啟用AOF持久化的應用都無法容忍這樣的損失,這就需要Redis在寫入AOF文件后主動要求系統將緩存內容同步到硬盤中。

AOF重寫機制

隨着命令不斷寫入AOF,文件會越來越大,為了解決這個問題,Redis引入了AOF重寫機制壓縮文件體積。AOF文件重寫是把Redis進程內的數據轉化為寫命令同步到新AOF文件的過程。

AOF重寫原理

重寫后的AOF文件為什么可以變小?有如下原因:

  1. 進程內已經超時的數據不再寫文件。
  2. 舊的AOF文件含有無效命令,如del key1、set a 111、set a 222等。重寫使用進程內數據直接生成,這樣新的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文件的大小超過所設定的閾值時,Redis就會對AOF文件的內容壓縮。

Redis 會fork出一條新進程,讀取內存中的數據,並重新寫到一個臨時文件中。並沒有讀取舊文件。最后替換舊的aof文件。

需要壓縮重寫的案例:
  • AOF帶來了另一個問題,持久化文件會變得越來越大。比如,我們調用INCR test命令100次,文件中就必須保存全部的100條命令,但其實99條都是多余的。

    • 因為要恢復數據庫的狀態其實文件中保存一條SET test 100就夠了。
  • 為了合並重寫AOF的持久化文件,Redis提供了bgrewriteaof命令。收到此命令后,Redis將使用與快照類似的方式將內存中的數據以命令的方式保存到臨時文件中,最后替換原來的文件,以此來實現控制AOF文件的合並重寫(會將重寫過程中接收的的新的指令和生成新的重寫后AOF文件中的指令進行合並)。

注意:由於是模擬快照的過程,因此在重寫AOF文件時並沒有讀取舊的AOF文件,而是將整個內存中的數據庫內容用命令的方式重寫了一個新的AOF文件

AOF重寫目的
  • AOF重寫降低了文件占用空間,除此之外,另一個目的是:更小的AOF文件可以更快地被Redis加載。
AOF重寫過程可以手動觸發和自動觸發:
  • 配置重寫rewrite觸發機制
    • 手動觸發:直接調用bgrewriteaof命令
    • 自動觸發:根據auto-aof-rewrite-min-size和auto-aof-rewrite-percentage參數確定自動觸發時機
      • auto-aof-rewrite-min-size: 限制了允許重寫的最小AOF文件,通常在AOF文件很小的時候即使其中有些冗余命令也可是可以忽略的。
      • auto-aof-rewrite-percentage: 當前的AOF文件大小超過上一次重寫的AOF文件大小的百分之多少時會再次進行重寫,如果之前沒有重寫過,則以啟動時的AOF大小為依據。

注意,執行AOF重寫請求時,父進程依然響應命令,Redis使用"AOF重寫緩沖區"保存這部分新數據,防止新AOF文件生成期間丟失這部分數據。

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

解釋含義:當AOF文件大小是上次rewrite后大小的一倍且文件大於64M時觸發。一般都設置為3G,64M太小了, 這里的“一倍”和“64M” 可以通過配置文件修改。


AOF與RDB二者選擇的標准(結合上一篇文章)

權衡的標准是對數據的一致性要求和性能之間的平衡。看系統是願意犧牲一些性能,換取更高的緩存一致性(AOF),還是願意寫操作頻繁的時候,不啟用備份來換取更高的性能,待手動運行save的時候,再做備份(RDB)。

AOF的執行流程

開啟AOF持久化后每執行一條會更改Redis中的數據的命令,Redis就會將該命令寫入硬盤中的AOF文件。

AOF的工作流程操作有:

  • 命令寫入(append)
  • 文件同步(sync)
  • 文件重寫(rewrite)
  • 重啟加載(load)

AOF流程如下:

  1. 所有的寫入命令會追加到aof_buf(緩沖區)中。
  2. AOF緩沖區根據對應的策略向硬盤做同步操作。
  3. 隨着AOF文件越來越大,需要定期對AOF文件進行重寫,達到壓縮的目的。
  4. 當Redis服務重啟時,可以加載AOF文件進行數據恢復。

AOF重啟加載

  • AOF和RDB文件都可以用於服務器重啟時的數據恢復。

    1. AOF持久化開啟且存在AOF文件時,優先加載AOF文件;

    2. AOF關閉或者AOF文件不存在時,加載RDB文件;

    3. 加載AOF/RDB文件城后,Redis啟動成功;

    4. AOF/RDB文件存在錯誤時,Redis啟動失敗並打印錯誤信息。

根據AOF文件恢復數據

正常情況下,將appendonly.aof 文件拷貝到redis的安裝目錄的bin目錄下,重啟redis服務即可。但在實際開發中,可能因為某些原因導致appendonly.aof 文件格式異常,從而導致數據還原失敗,可以通過命令redis-check-aof --fix appendonly.aof 進行修復 。從下面的操作演示中體會。

若打算使用Redis 的持久化。建議RDB和AOF都開啟。其實RDB更適合做數據的備份,
留一后手。AOF出問題了,還有RDB。

AOF 的優缺點

AOF 優點

數據的完整性和一致性更高

AOF劣勢

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

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

  • 數據的完整性和一致性更高因為AOF記錄的內容多,文件會越來越大,數據恢復也會越來越慢。

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

總結

每秒同步策略的效率是比較高的,同步禁用策略的效率和RDB一樣高效。

  • AOF 的數據完整性比RDB高,但記錄內容多了,會影響數據恢復的效率。
  • RDB與AOF二者選擇的標准,就是看系統是願意犧牲一些性能,換取更高的緩存一致性(aof),還是願意寫操作頻繁的時候,不啟用備份來換取更高的性能,待手動運行save的時候,再做備份(rdb)。
  • Redis允許同時開啟AOF和RDB,既保證了數據安全又使得進行備份等操作十分容易。此時重新啟動Redis后Redis會使用AOF文件來恢復數據,因為AOF方式的持久化可能丟失的數據更少。
  • 若只打算用Redis 做緩存,可以關閉持久化。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM