Redis的兩種持久化機制

Redis的兩種持久化機制

1、持久化機制

client—>redis(內存)—>內存數據-數據持久化—>磁盤

兩種方法

  • 快照(Snapshot)
  • AOF(Append Only File)只追加日誌文件

2、快照

2.1 特點

這種方式可以將某一時刻的所有數據寫入到硬盤中,這也是redis的默認開啟持久化方式,保存的文件是以.rdb結尾的文件,因此這種方式也被稱為RDB方式。官方的說法叫快照持久化。

image-20220512214029142

2.2 快照生成方式

  • 客戶端方式:BGSAVE和SAVE指令

  • 服務器配置自動觸發

    客戶端方式1:BGSAVE
    客戶端可以使用BGSAVE命令來創建一個快照,當接收到客戶端的這個命令後,redis會調用fork操作來創建一個子進程,然後子進程負責把這個快照寫入到磁盤中,而父進程繼續處理命令請求
    
    什麼是fork:fork是linux系統的調用:在當前進程中,fork一個子進程,子進程最初與主進程是共享一份內存區域的。由於主進程不斷進行數據的寫操作,與子進程存在並發衝突問題。此時,redis採用寫時複製技術(cow):
    當主進程寫操作時,首先會複製一份將要涉及寫操作的內存頁。然後主進程在新複製的內存頁上進行寫操作,原有內存頁繼續供子進程持久化。
    

    image-20220512214729500

    客戶端方式2:SAVE
    客戶端還可以使用SAVE命令來創建一個快照,接收到SAVE命令的redis服務器會在快照創建完畢之前不再響應任何其他命令
    

    注意:SAVE命令並不常用,使用SAVE命令在快照創建完畢之前,redis處於阻塞狀態,無法對外服務

    image-20220512214914633

    服務器配置自動觸發:
    如果用戶在redis.conf中設置了save配置選項,redis會在save選項條件滿足之後自動觸發一次BGSAVE命令,如果設置多個save配置選項,每當任意一個save配置選項條件滿足,redis也會觸發一次BGSAVE命令
    
    服務器接收客戶端shutdown指令
    - 當redis通過shutdown指令接收到關閉服務器的請求時,會執行一個save命令,阻塞所有的客戶端,不再執行客戶端執行發送的任何命令,並且在save命令執行完畢之後關閉服務器
    

3.AOF方式——只追加日誌文件

3.1 特點

這種方式可以將所有客戶端執行的寫命令記錄到日誌文件中,AOF持久化會將被執行的寫命令寫到AOF的文件末尾,來記錄數據發生的變化,因此只要redis從頭到尾執行一次AOF文件所包含的所有寫命令,就可以恢復AOF文件的記錄的數據集。

image-20220512222000591

3.2 開啟AOF持久化

1.修改 appendonly yes 開啟持久化
2.修改 appendfilename "appendonly.aof" 指定生成文件名稱

image-20220816194444859

image-20220816194623703

3.3 日誌追加頻率

1.always[謹慎使用]
說明:每個redis命令都要同步寫入硬盤,嚴重降低redis速度,這種方式可以將發生系統崩潰時丟失的數據減少到最少,但是由於這種方式要對硬盤進行大量的寫入操作,所以redis處理命令的速度會受到硬盤性能的限制。機械硬盤在這種頻率下200左右個命令/s ;固態硬盤(SSD)大概幾百萬個命令/s;使用SSD用戶請謹慎使用always選項,這種模式不斷寫入少量數據的做法有可能會引發嚴重的`寫入放大`問題,導致將固態硬盤的壽命從原來的幾年降低為幾個月。

2.everysec[推薦默認]
說明:每秒執行一次同步,將多個寫命令同步到磁盤。即使系統崩潰也最多丟失一秒的數據。

3.no[不推薦]
說明:完全由操作系統決定什麼時候同步AOF文件,這個選項不會對redis性能帶來影響,但是當系統崩潰時,會丟失不定量的數據,甚至是全部數據。另外如果用戶硬盤處理寫入操作不夠快的話,當緩衝區被等待寫入硬盤數據填滿時,redis會處於阻塞狀態,並導致redis的處理命令請求的速度變慢。

3.4 修改同步頻率

修改appendfsync everysec|always|no 指定

3.5 AOF文件的重寫

3.5.1 出現的問題

AOF方式會出現一個問題,持久化文件會越來越大,例如我們調用incr test命令100次,文件中必須保存全部的100條命令,其實有99條都是多餘的。因為要恢複數據庫的狀態其實文件中保存一條set test 100就夠了。為了壓縮aof的持久化文件Redis提供了AOF重寫機制

3.5.2 AOF重寫

用來在一定程度上減少AOF文件的體積,並且保證數據不丟失

3.5.3 觸發AOF重寫的方式

1.客戶端方式
執行BGREWRITEAOF命令,不會阻塞redis服務

2.服務器配置方式自動觸發
配置redis.conf中的auto-aof-rewrite-percentage選項 參加下圖↓↓↓
- 如果設置auto-aof-rewrite-percentage值為100和auto-aof-rewrite-min-size 64mb,並且啟用的AOF持久化時,那麼當AOF文件體積大於64M,並且AOF文件的體積比上一次重寫之後體積大了至少一倍(100%)時,會自動觸發,如果重寫過於頻繁,用戶可以考慮將auto-aof-rewrite-percentage設置為更大

image-20220512225431013

3.5.4 重寫原理

開啟AOF持久化後生成一個appendonlydir文件夾,這個文件夾下有如下三個文件

image-20220816201657804

從Redis 7.0.0 開始,Redis使用了多部分AOF 機制。也就是將原來的單個AOF文件拆分為基礎文件(最多一個)和增量文件(可能不止一個)。基本文件表示重寫AOF 時存在的數據的初始(RDB 或 AOF 格式)快照。所有這些文件都放在一個單獨的目錄中,並由清單文件跟蹤。

image-20220513120013948

重寫過程:在觸發AOF重寫後,redis調用fork創建一個子進程,子進程根據此時的數據狀態生成快照,同時主進程會創建一個新的增量文件用來繼續處理客戶端傳來的命令請求,子進程將這個快照文件以命令的形式寫入臨時文件,當快照往臨時文件寫完後,通知主進程把新的增量文件和子進程生成的基礎文件構建成臨時清單,並將其持久化,redis對清單文件進行原子交換,使AOF重寫的結果生效,生成一個新的基礎文件,並且創建一個新的aof增量文件來接收命令。

image-20220816205803669

4.持久化總結

兩種持久化方案既可以同時使用,又可以單獨使用,在某種情況下也可以都不使用,具體使用那種持久化方案取決於用戶的數據和應用決定。

無論使用AOF還是快照機制持久化,將數據持久化到硬盤都是有必要的,除了持久化外,用戶還應該對持久化的文件進行備份(最好備份在多個不同地方)。

Tags: