詳解Redis的AOF持久化方式


為什么需要持久化,以及Redis持久化的RDB方式在這篇文章講的已經很透徹了,足以吊打面試官了。而且此篇內容需要RDB文章的內容支持,所以建議先看下:詳解Redis的RDB持久化方式

一、什么是AOF

它也是Redis持久化的重要手段之一,aof->Append Only File,只追加文件,也就是每次處理完請求命令后都會將此命令追加到aof文件的末尾。而RDB是壓縮成二進制等時機開子進程去干這件事。

二、優缺點

1、優點

  • 持久化的速度快,因為每次都只是追加,rdb每次都全量持久化

  • 數據相對更可靠,丟失少,因可以配置每秒持久化、每個命令執行完就持久化

2、缺點

  • 災難性恢復的時候過慢,因為aof每次都只追加原命令,導致aof文件過大,但是后面會rewrite,但是相對於rdb也是慢的。

  • 會對主進程對外提供請求的效率造成影響,接收請求、處理請求、寫aof文件這三步是串行原子執行的。而非異步多線程執行的。Redis單線程!

三、AOF原理

1、基礎原理

就是每次都在aof文件后面追加命令。他與主進程收到請求、處理請求是串行化的,而非異步並行的。圖示如下



在這里插入圖片描述


所以aof的頻率高的話絕逼會對Redis帶來性能影響,因為每次都是刷盤操作。跟mysql一樣了。Redis每次都是先將命令放到緩沖區,然后根據具體策略(每秒/每條指令/緩沖區滿)進行刷盤操作。如果配置的always,那么就是典型阻塞,如果是sec,每秒的話,那么會開一個同步線程去每秒進行刷盤操作,對主線程影響稍小。

2、額外擴展

其實Redis每次在寫入AOF緩沖區之前,他都會調用flushAppendOnlyFile(),判斷是否需要將AOF緩沖區的內容寫入和同步到AOF文件中。這個決策是由配置文件的三個策略來控制的

  • always

  • everysec

  • no

四、REWRITE

1、為什么要rewrite?

比如我有業務很簡單,就來回delete set 同一個key。就這個業務運行了10年,那么aof文件將記錄無數個delete k1, set k1 xxx。其實都是重復的,但是我aof每次都追加,文件變成了1T大小。這時候Redis宕機了,要恢復,你想想1TB大小的aof文件去恢復,累死了。最主要的是1TB大小只記錄了兩個命令,所以壓縮其實就是來處理這件事的。

2、4.0版本之前的rewrite

Redis4.0之前和Redis4.0的rewrite(重寫)方式不一樣,Redis4.0之前就是將aof文件中重復的命令給去掉。保留最新的命令。進而減少aof文件大小。比如

set k1 123
set k1 345
del k1
set k1 789

經過rewrite后(Redis4.0之前),只會變成如下

set k1 789

3、4.0版本以及之后的rewrite

4.0之前的做法效率很是低下,需要逐條命令對比。4.0開始的rewrite支持混合模式(也是就是rdb和aof一起用),直接將rdb持久化的方式來操作將二進制內容覆蓋到aof文件中(rdb是二進制,所以很小),然后再有寫入的話還是繼續append追加到文件原始命令,等下次文件過大的時候再次rewrite(還是按照rdb持久化的方式將內容覆蓋到aof中)。但是這種模式也是配置的,默認是開,也可以關閉。

4、rewrite觸發條件

1、手動觸發

  • 客戶端執行bgrewriteaof命令

2、自動觸發

通過以下兩個配置協作觸發

auto-aof-rewrite-min-size

AOF文件最小重寫大小,只有當AOF文件大小大於該值時候才可能重寫,4.0默認配置64mb。

auto-aof-rewrite-percentage

當前AOF文件大小和最后一次重寫后的大小之間的比率等於或者等於指定的增長百分比,如100代表當前AOF文件是上次重寫的兩倍時候才重寫。 

3、觸發滿足條件

  • 沒有BGSAVE命令(RDB持久化)/AOF持久化在執行

  • 沒有BGREWRITEAOF在進行;

前兩點也就是說只允許同時fork()一個子進程出來干活。

  • 當前AOF文件大小要大於server.aof_rewrite_min_size的值;

  • 當前AOF文件大小和最后一次重寫后的大小之間的比率等於或者大於指定的增長百分比(auto-aof-rewrite-percentage參數)

5、rewrite原理

4.0之前版本的,和4.0以及之后關閉混合模式的情況下。


在這里插入圖片描述
  • aof_rewrite_buf:rewrite(重寫)緩沖區、aof_buf:寫命令存放的緩沖區

  • 開始bgrewriteaof的時候,判斷當前有沒有bgsave/bgrewriteaof在執行,若有,則不執行,這個再rdb篇幅也有提到,以及下面很多fork()知識在rdb都有提到。詳解Redis的RDB持久化方式

  • 主進程fork()出子進程,在執行fork()這個方法的時候是阻塞的,子進程創建完畢后就不阻塞了

  • 主進程fork完子進程后,主進程能繼續接收客戶端的請求,所有寫命令依然是寫入AOF文件緩沖區並根據配置文件的策略同步到磁盤的。

  • 因為fork的子進程僅僅共享主進程fork()時的內存,后期主進程在更改內存數據,子進程是不可見的。因此Redis采取重寫緩沖區(aof_rewite_buf)保存fork之后的客戶端請求。防止新AOF文件生成期間丟失主進程執行的新命令所生成的數據。所以此時客戶端的寫請求不僅僅寫入原來的aof_buf緩沖區,還寫入了重寫緩沖區。這就是我為什么用深藍色的框給他兩框到一起的原因。

  • 子進程通過內存快照的形式,開始生成新的aof文件。

  • 新aof文件生成完后,子進程向主進程發信號。

  • 主進程收到信號后,會把重寫緩沖區(aof_rewite_buf)中的數據寫入到新的AOF文件(主要是避免這部分數據丟失)

  • 使用新的AOF文件覆蓋舊的AOF文件,且標記AOF重寫完成。

五、RDB-AOF混合持久化

redis4.0之后才支持,默認開啟

1、優點

混合持久化結合了RDB持久化 和 AOF 持久化的優點,采取了rdb的文件小易於災難恢復,同時結合AOF,增量的數據以AOF方式保存了,數據更少的丟失。

2、缺點

兼容性差,一旦開啟了混合持久化,在4.0之前版本都不識別該aof文件,同時由於前部分是RDB格式,需要專業的工具來閱讀,因為是二進制,所以閱讀性較差。

3、原理

需要先掌握詳解Redis的RDB持久化方式和此篇幅的aof

混合持久化也是通過bgrewriteaof完成的,所以基本流程和上述一樣。不同的是當開啟混合模式時,fork出的子進程先將共享的內存副本全量以RDB的方式寫入aof。這樣提高了速度也極大的縮小了aof文件(畢竟都是二進制)。寫完還是通知主進程,然后再將重寫緩沖區的內容以AOF方式寫入到文件,然后替換舊的aof文件。也就是說這種模式下的aof文件發生rewrite后前半部分是rdb格式(REDIS開頭的二進制數據),后半部分是正常的aof追加的命令(重寫緩沖區里的)。

4、數據恢復

會優先看是否存在aof文件,若存在則先按照aof文件恢復,因為aof畢竟比rdb全。若aof不存在,則才會查找rdb是否存在。這是默認的機制。畢竟aof文件也rewrite成rdb二進制格式,文件小,易於回復。所以redis會優先采取aof。

六、總結

此篇都是重點,廢話很少。沒啥可總結的。


免責聲明!

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



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