Redis 中兩種持久化機制詳解

Redis 是 內存數據庫,但是它也能夠將存儲的數據保存在硬盤上,這是由於它的持久化機制。

Redis 官方提供了兩種不同的持久化方法來將數據存儲到硬盤裏面分別是:

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

快照 (Snapshot)

這種方式可以將某一時刻的所有數據都寫入硬盤中,這也是Redis 的默認開啓持久化方式,保存的文件是以 .rdb 形式結尾的文件,因此這種方式也稱之爲 RDB方式。
在這裏插入圖片描述
快照生成方式:

  • 客戶端方式:BGSAVESAVE 指令
  • 服務器配置自動觸發
  • 服務器 SHUTDOWN 自動觸發

1. 客戶端方式之 BGSAVE(多線程執行)

客戶端可以使用 BGSAVE 命令來創建一個快照,當接收到客戶端的 BGSAVE 命令時,Redis 會調用 fork 來創建一個子進程,然後子進程負責將快照寫入磁盤中,而父進程則繼續處理命令請求。

fork:當一個進程創建子進程的時候,底層的操作系統會創建該進程的一個副本,在類unix系統中創建子進程的操作會進行優化:在剛開始的時候,父子進程共享相同內存,直到父進程或子進程對內存進行了寫之後,對被寫入的內存的共享纔會結束服務。

在這裏插入圖片描述

2. 客戶端方式之 SAVE(單線程執行)

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

注意:SAVE 命令並不常用,使用 SAVE 命令在快照創建完畢之前,Redis處於阻塞狀態,無法對外服務。
在這裏插入圖片描述

3. 服務器配置方式之 配置快照觸發條件

如果用戶在 redis.conf 中設置了 save 配置選項,Redis 會在 save 選項條件滿足之後自動觸發一次 BGSAVE 命令;如果設置多個 save 配置選項,當任意一個 save 配置選項條件滿足,Redis 也會觸發一次 BGSAVE 命令。
在這裏插入圖片描述
save 900 1 表示 900s 內,執行了 1次 數據庫操作則自動創建快照,以此類推。

4. 服務器接收客戶端 SHUTDOWN 指令

當 Redis 通過 SHUTDOWN 指令接收到關閉服務器的請求時,會執行一個 SAVE 命令,阻塞所有的客戶端,不再執行客戶端執行發送的任何命令,並且在 SAVE 命令執行完畢之後關閉服務器。

配置文件中配置生成快照名稱和位置

配置文件中可以修改生成快照名稱以及快照保存位置:

# 生成快照名字, 默認爲 dump.rdb
dbfilename dump.rdb

# 快照保存位置, 默認保存在 redis-cli 同級目錄
dir ./ 

在這裏插入圖片描述

只追加日誌文件 AOF (Append Only File)

在 Redis 的默認配置中 AOF持久化機制是沒有開啓的,需要在配置中開啓;

# 開啓 AOF持久化
appendonly yes

# 生成的日誌文件名稱
appendfilename "appendonly.aof"

# aof日誌文件路徑與快照保存位置設置的是同一個
dir ./ 

在這裏插入圖片描述
AOF 有 3 種 日誌追加頻率:

  • always 【謹慎使用】
  • everysec 【推薦】
  • no【不推薦】

1.always【謹慎使用】

  • 說明:每個 redis寫命令 都要同步寫入硬盤,嚴重降低 redis 速度;
  • 解釋:如果用戶使用了 always 選項,那麼每個 redis 寫命令都會被寫入硬盤,從而將發生系統崩潰時出現的數據丟失減到最少;遺憾的是,因爲這種同步策略需要對硬盤進行大量的寫入操作,所以 redis 處理命令的速度會受到硬盤性能的限制;
  • 注意:轉盤式硬盤(機械硬盤)在這種頻率下200左右個命令/s;固態硬盤(SSD) 幾百萬個命令/s;
  • 警告:使用SSD用戶請謹慎使用 always 選項,這種模式不斷寫入少量數據的做法有可能會引發嚴重的 寫入放大 問題,導致將固態硬盤的壽命從原來的幾年降低爲幾個月。

2.everysec【推薦】

  • 說明:每秒 執行一次同步顯式的將多個寫命令同步到磁盤;
  • 解釋:爲了兼顧數據安全和寫入性能,可以使用 everysec 選項,讓 redis 每秒一次的頻率對AOF文件進行同步;redis 每秒同步一次AOF文件時性能和不使用任何持久化特性時的性能相差無幾,而通過每秒同步一次AOF文件,redis可以保證,即使系統崩潰,用戶最多丟失一秒之內產生的數據。

3.no【不推薦】

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

配置文件中修改同步頻率

# appendfsync always
appendfsync everysec 
# appendfsync no

在這裏插入圖片描述

AOF文件重寫機制

AOF帶來的問題

AOF的方式也同時帶來了另一個問題:持久化文件會變的越來越大。

例如我們調用 incr test 命令 100 次,文件中必須保存全部的 100 條命令,其實有 99 條都是多餘的,因爲要恢復數據庫的狀態其實文件中保存一條 set test 100 就夠了。爲了壓縮 AOF 的持久化文件,Redis 提供了 AOF重寫(ReWriter)機制

AOF 重寫機制 在一定程度下減少 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%(1倍) 時,自動觸發重寫。 如果重寫過於頻繁,可以考慮將 auto-aof-rewrite-percentage 設置的更大。

重寫原理

注意:重寫 aof文件 的操作,並沒有讀取舊的 aof文件,而是將整個內存中的數據庫內容用命令的方式重寫了一個新的 aof文件,替換原有的文件,這點和快照有點類似。

重寫流程

  1. redis 調用 fork,現在有父子兩個進程,子進程根據內存中的數據庫快照,往臨時文件中寫入重建數據庫狀態的命令;
  2. 父進程繼續處理 client 請求,除了把寫命令寫入到原來的 aof文件 中,同時 把收到的寫命令緩存起來,這樣就能保證如果子進程重寫失敗的話並不會出問題。
  3. 當子進程把快照內容寫入已命令方式寫到臨時文件中後,子進程發信號通知父進程,然後父進程把緩存的寫命令也寫入到臨時文件。
  4. 現在父進程可以使用臨時文件替換老的 aof文件,並重命名,後面收到的寫命令也開始往新的 aof文件 中追加。

在這裏插入圖片描述

Redis 持久化總結

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

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章