Redis - 資料持久性設定

不同情境下 Redis 資料持久性設定建議

ta-ching chen

2 minute read

前言

大型網站、平台往往需要透過緩存來儲存靜態、異動量較少的資料,減緩後端伺服器的負載,而目前 Redis 與 Memcached 兩套皆是非常流行的儲存資料庫。以下會介紹在 Redis 的資料持久性 (data persistence) 該如何設定才足以應付日常營運需求 (內文主要針對需要注意的設定進行講解,完整 Redis 設定請見官方設定)。

寫在前頭,Redis Persistence 很可能跟你想的不一樣

Redis 是「緩存」而非永久儲存用的資料庫

偶爾聽到有人會將資料定期倒入 Redis 存放,但資料持久性的功能應當視為在出現異常時,服務能在短時間回復的最後手段。「緩存」裡面資料最終都要能夠透過任何方式還原,才是較為正確的做法。

資料持久性設定

Redis 目前擁有兩種資料持久性的格式: RDB、AOF

  • RDB:
    • 優點: 備份頻率較 AOF 低,但檔案小、適合作為災難還原的備份檔
    • 缺點: 當服務異常停止時,部分數據可能會遺失

設定的格式為 save <seconds> <changes>,意思是當過 X 秒後且有 Y 個鍵值改變即備份資料。

# Default Setting
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes

當設定的條件被觸發時,Redis 會 fork() 出子進程 (child process) 在背景進行備份

  • AOF:
    • 優點: 紀錄所有寫入 (Write) 動作的,備份頻率、完整性較 RDB 高
    • 缺點: 檔案大,還原時間較長,不適合備份
# Default Setting
appendonly no
appendfilename "appendonly.aof"

在兩種持久性設定都打開的情況下,由於每次的寫入操作皆會被保存進 AOF ,使得它的資料完整度較高,因此 Redis 在重啟後會選擇讀取 AOF 檔案進行還原。若 AOF 設定為關閉的狀況,才會選用 RDB 進行還原。

設定前的捫心自問

在開始資料持久性設定前,我們首先需要考量以下幾個問題點:

  • 是否有其他方式重建(還原)資料

由於資料的重要性與來源不同,是否有簡便的方式能夠將資料還原會是線上營運很關鍵的一環。如果資料可以透過從遠端資料庫取得並寫入緩存的話,建議將備份關閉以提高緩存性能。但若現存沒有任何方式可以快速還原的話 RDB、AOF 兩種備份方式建議都打開,前者提供可異地備援的單一檔案在避免意外發生後還能復原,後者則提供資料完整度高的備份檔。

  • 可容許資料遺失範圍

由於備份會對額外消耗 CPU 資源,部分情況下會對 Redis 效能產生一定影響。資料遺失敏感度低的服務,建議可以關閉 AOF 僅保留 RDB。資料遺失敏感度高的服務則將 RDB 的備份頻率調高,另外定期異地備份該 RDB 檔。

  • 服務可用性或資料持久性,何者優先度高

Redis 的 RDB 備份在背景失敗時可以根據設定選擇是要停止運作直到問題解決或忽略錯誤繼續服務。根據過去經驗可能會遇到記憶體不足、硬碟空間不夠、CPU 忙碌導致失敗,需要根據你的服務運作模式來做出適當的設定。

不同情境設定建議

  • 資料可完全遺失、低延遲優先

比方說緩存內記錄的是 user session 遺失不影響運作,且可以在營運過程中重新建立,這種情況會建議將兩種備份都關閉,以提高服務性能。

save ""
appendonly no
  • 資料可部分遺失、低延遲優先

RDB 備份頻率受到資料敏感程度影響,比方說允許最近 5 分鐘內的資料遺失就可以選擇 save 300 100 之類的設定,但實際上備份頻率要根據你的服務應用場景決定。希望低延遲優先的話,可以選擇將 AOF 關閉,避免不必要的備份。

# RDB
save 900 1
save 300 10
save 60  10000

# Stop to serve write operation when backup failed
stop-writes-on-bgsave-error yes

# AOF
appendonly no
  • 資料完整度優先 (不推薦)

將 RDB、AOF 兩種備份方式皆開啟,提高 RDB 備份頻率並進行異地備份。

請勿仰賴此方式將 Redis 當做資料庫永久儲存

# RDB
save 300 10
save 100 100
save 60  1000

# Stop to serve write operation when backup failed
stop-writes-on-bgsave-error yes

# AOF
appendonly yes
  • (Optional) 備份失敗是否繼續服務

前述的兩種情境: 1) 資料可部分遺失、低延遲優先,2) 資料完整度優先,根據不同場景可以決定失敗時 Redis 的行為,並修改以下設定:

若希望備份失敗時能如實反應異常的話

stop-writes-on-bgsave-error yes

若失敗也沒關係或已有其他方式監控 Redis 異常的話

stop-writes-on-bgsave-error no

Troubleshooting

  • 備份失敗,導致無法進行寫入

MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error.

表示備份失敗,並由於設定 stop-writes-on-bgsave-error yes 導致停止處理寫入請求,處理方式有兩種:

  1. 找到失敗原因並解決,比方說硬碟不足、記憶體不夠導致無法 fork() 子進程
  2. 設定改成 stop-writes-on-bgsave-error no
  • 備份失敗,導致 Redis 停止運作

看日誌通常會出現下列錯誤

# redis log
533:S 04 May 16:38:01.698 # Background saving terminated by signal 9

# dmesg
[5040907.165916] Out of memory: Kill process 533 (redis-server) score 843 or sacrifice child
[5040907.174246] Killed process 10417 (redis-server) total-vm:1605792kB, anon-rss:1513192kB, file-rss:4kB

明顯看出因為 Redis fork() 子進程時導致 OOM (Out of memory) 使得 Redis process 被 OS 強制停止,唯一的解法就是加大記憶體容量,通常建議保持在總記憶體 6 成左右的用量。

參考網頁

comments powered by Disqus