Redis面試寶典-持久化篇

chenoracle發表於2022-07-30

一:Redis持久化有哪些方式?
二:RDB持久化觸發方式有哪些?
三:RDB持久化優缺點?
四:簡述bgsave過程?
五:簡述AOF工作流程?
六:AOF緩衝區同步檔案策略有哪些?
七:AOF重寫觸發條件?
八:簡述AOF重寫過程?
九:RDB和AOF持久化檔案損壞如何處理?

一: Redis持久化有哪些方式?

1.RDB 持久化

將當前程式資料生成快照儲存到硬碟。

 

2.AOF 持久化 (append only file)

以獨立日誌方式記錄每次寫命令,重啟時再重新執行 AOF 檔案中的命令達到恢復資料的目的。 AOF 的主要作用是解決了資料持久化的實時性,目前已經是 Redis 持久化的主流方式。

二: RDB 持久化觸發方式有哪些?

觸發 RDB 持久化過程分為手動觸發和自動觸發。

手動觸發命令有 save bgsave

save 命令:阻塞當前 Redis 伺服器,直到 RDB 過程完成為止,對於記憶體較大的例項會造成長時間阻塞,線上環境不建議使用,執行 save 命令對於 Redis 日誌如下 :

* DB saved on disk

 

bgsave 命令:

Redis 程式執行 fork 操作建立子程式, RDB 持久化過程由子程式負責,完成後自動結束。

阻塞只發生 fork 階段,一般時間較短。執行 bgsave 命令對應 redis 日誌如下 :

* Backgroup saving start by pid xxx

* DB saved on disk

* RDB:0 MB of memory used by copy-on-write

* Backgroup saving terminated with success

 

RDB 自動觸發有如下幾個場景:

1. 使用 save 相關配置,如 save m n 。表示 m 秒內資料集存在 n 次修改時,自動觸發 bgsave

2. 從節點執行全量複製操作,主節點自動執行 bgsave 生成 RDB 檔案併傳送給從節點。

3. 執行 debug reload 命令重新載入 redis 時。

4. 預設情況下執行 shutdown 命令時,如果沒有開啟 AOF 持久化功能,則自動執行 bgsave


三: RDB 持久化優缺點?

優點 :

1.RDB 是一個緊湊壓縮的二進位制檔案,代表 Redis 在某個時間點上的資料快照,適合用於備份,全量複製等場景。

2.Redis 載入 RDB 恢復資料遠遠快於 AOF 的方式。

缺點:

1.RDB 方式資料沒辦法做到實時持久化 / 秒級持久化。

2.bgsave 每次執行都需要執行 fork 操作建立子程式,屬於重量級操作,頻繁執行成本過高。

3.RDB 檔案使用特定二進位制格式儲存, Redis 版本演進過程中有多個格式 RDB 版本,存在老版本 Redis 服務無法相容新版本 RDB 格式的問題。

四:簡述 bgsave 過程?

1. 執行 bgsave 命令, Redis 父程式判斷當前是否存在正在執行的子程式,如果 RDB/AOF 子程式,如果存在,直接返回。

2. 父程式執行 fork 操作建立子程式, fork 操作過程中父程式會阻塞,透過 info stats 命令檢視 lastest_fork_usec 選項,可以獲取最近一個 fork 操作耗時,單位為微秒。

fork 建立子程式不需要複製父程式實體記憶體空間,但是會複製父程式空間記憶體頁表。例如 10GB redis 程式,需要複製大約 20MB 的記憶體頁表,因此 fork 操作耗時跟程式總記憶體量息息相關。

對於高流量的 redis 例項 OPS(operation per second 每秒操作次數 ) 可達 5 萬以上,如果 fork 操作耗時在秒級別,將會拖慢 redis 幾萬條命令執行。正常情況下 fork 耗時應該是每 GB 耗時 20 毫秒左右。

3. 父程式 fork 完成後, bgsave 命令返回” Backgroup saving started “資訊並不再阻塞父程式,可以繼續響應其他命令。

4. 子程式建立 RDB 檔案,根據父程式記憶體生成臨時快照檔案,完成後對原有檔案進行原子替換。執行 lastsave 命令可以獲取最後一次生成 RDB 時間,對應 inof 統計的 rdb_last_save_time 選項。

5. 程式傳送訊號給父程式表示完成,父程式更新統計資訊,具體見 info Persistence 下的 rdb_* 相關選項。

五:簡述 AOF 工作流程

1. 所有寫命令會追加到 aof_buf( 緩衝區 ) 中。

2.AOF 快取區根據對應的策略向硬碟做同步操作。

3. 隨著 AOF 檔案越來越大,需要定期對 AOF 檔案進行重寫,達到壓縮的目的。

4. Redis 伺服器重啟時,可以載入 AOF 檔案進行資料恢復。

六: AOF 緩衝區同步檔案策略有哪些?

由引數 appendfsync 控制,主要有下面三種配置:

1.always

命令寫入 aof_buf 後呼叫系統 fsync 操作同步到 AOF 檔案, fsync 完成後返回。

2.everysec

命令寫入 aof_buf 後呼叫系統 write 操作, write 完成後執行緒返回。 fsync 同步檔案操作由專門執行緒每秒呼叫一次。這也是建議的同步策略,也是預設配置,做到兼顧效能和資料安全性。

3.no

命令寫入 aof_buf 呼叫系統 write 操作,不對 AOF 檔案做 fsync 同步,同步硬碟操作由作業系統負責,通常同步週期最長 30 秒。

七: AOF 重寫觸發條件?

手動觸發:

直接呼叫 bgrewriteaof 命令。

 

自動觸發:

根據 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 統計資訊中檢視。

八:簡述 AOF 重寫過程

1. 執行 AOF 重寫請求。

如果當前程式正在執行 AOF 重寫,請求不執行並返回如下響應 :

ERR Backgroud append only file rewriting already in progress

如果當前程式正在執行 bgsave 操作,重寫命令延時到 bgsave 完成之後再執行,返回如下響應: Background append only file rewriting scheduled

2. 父程式執行 fork 建立子程式,開銷等同於 bgsave 過程。

3. 主程式 fork 操作完成後,繼續響應其他命令。所有修改命令依然寫入 AOF 緩衝區,並根據 appendfsync 策略同步到硬碟,保證原有 AOF 機制正確性。

由於 fork 操作運用寫時複製技術,子程式只能共享 fork 操作時的記憶體資料。由於父程式依然響應命令, Redis 使用 AOF 重寫緩衝區儲存這部分新資料,防止新 AOF 檔案生成期間丟失這部分資料。

4. 子程式根據記憶體快照,按照命令合併規則寫入到新 AOF 檔案。每次批次寫入硬碟資料量由配置 aof-rewrite-incremental-fsync 控制,預設 32MB ,防止單次刷盤資料過多造成硬碟阻塞。

5. AOF 檔案寫入完成後,子程式傳送訊號給父程式,父程式更新統計資訊,具體見 info persistence 下的 aof_* 相關統計。

父程式把 AOF 重寫緩衝區的資料寫入到新的 AOF 檔案。

使用新 AOF 檔案替換老檔案,完成 AOF 重寫。

九: RDB AOF 持久化檔案損壞如何處理?

1.RDB 檔案損壞

RDB 檔案儲存位置在 dir 配置指定的目錄下,檔名透過 dbfilename 配置指定。

可以透過執行 config set dir {newDir} confg set dbfilename {newFileName} 動態修改,當下次執行 RDB 檔案會儲存到新目錄。

當遇到壞盤或磁碟寫滿等情況,可以透過 config set dir {newDir} 線上修改檔案路徑到可用磁碟路徑,之後執行 bgsave 進行磁碟切換,同樣適用於 AOF 持久化檔案。

如果在 redis 啟動時載入的 RDB 檔案已經損壞,會拒絕啟動,並列印如下日誌:

Short read or OOM loading DB. Unrecoverable error,aborting now.

這時可以使用 redis 提供的 redis-check-dump 工具檢測 RDB 檔案並獲取對應的錯誤報告。

 

2.AOF 檔案損壞

對於錯誤格式的 AOF 檔案,先進行備份,然後採用 redis-check-aof --fix 命令進行修復,修復後使用 diff -u 對比資料差異,找出丟失資料,有些可以人工修補全。

AOF 檔案可能存在結尾不完整的情況,比如機器突然斷電導致 AOF 尾部檔案命令寫入不全。 Redis 提供了 aof-load-truncated 配置來相容這種情況,預設開啟。載入 AOF 時,當遇到此問題時會忽略並繼續啟動,同時列印如下警告日誌 :

# !!! Warning: short read while loading the AOF file !!!

# !!! Truncatin the AOF at offset xxxxxx!!!

# AOF loaded anyway because aof-load-truncated is enabled

十:簡述 AOF 追加阻塞

當開啟 AOF 持久化時,常用的同步硬碟的策略是 everysec ,用於平衡效能和資料安全性。對於這種方式, Redis 使用另一條執行緒每秒執行 fsync 同步硬碟。當系統硬碟資源繁忙時,會造成 redis 主執行緒阻塞。

阻塞流程分析:

1. 主執行緒負責寫入 AOF 緩衝區。

2.AOF 執行緒負責每秒執行一次同步磁碟操作,並記錄最近一次同步時間。

3. 主執行緒負責對比上次 AOF 同步時間 :

如果距離上次同步成功時間在 2 秒內,主執行緒直接返回。

如果距離上次同步成功時間超過 2 秒,主執行緒將會阻塞,直到同步完成。

當發生 AOF 追加阻塞時,在 info Persistence 統計中, aof_delayed_fsync 指標會累加,檢視這個指標方便定位 AOF 阻塞問題。日誌會提示如下內容 :

Asynchronous AOF fsync is taking too long (disk is busy?). Writing the AOF buffer without waiting for fsync to complete,this may slow down Redis.

 

透過 AOF 阻塞流程可以發現兩個問題:

1.everysec 配置最多可能丟失 2 秒資料,不是 1 秒。

2. 如果系統 fsync 緩慢,將會導致 Redis 主執行緒阻塞,影響效率。

參考:《 Redis 開發與運維》


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29785807/viewspace-2908298/,如需轉載,請註明出處,否則將追究法律責任。

相關文章