接下來兩篇將記錄Redis持久化存儲兩大技術:AOF日志、RDB快照
本篇重點
“AOF日志實現”
“AOF日志三種寫回策略”
“AOF重寫——避免日志過大的解決方案”
前言
Redis持久化存儲兩大技術:AOF日志、RDB快照
AOF: Append Only File
RDB: Redis DB
背景
Redis運行中,若突然宕機,存儲在內存中的數據都會丟失。此時如果從后端數據庫恢復數據,雖然可行,但也會導致效率問題:
- 頻繁訪問數據庫增加數據庫壓力
- 慢速數據庫讀取導致Redis性能下降
因此,Redis實現數據持久化的方式,要避免從后端數據庫中恢復數據,采用的方式就是AOF日志和RDB快照,本篇文章主要討論AOF日志。
1. AOF日志實現
- 寫后日志:先執行命令,數據寫入內存;再記錄日志
- 日志記錄內容:Redis收到的每一條命令,記錄格式如下:
-
"*+number"——當前命令有number個字段,后面內容是對應字段描述
-
"$+number"——表示當前字段占用的字節數,后面跟具體字段名稱
-
例子:命令:
set testkey testvalue
,寫入AOF日志后的格式是*3 // 當前命令3個字段(分別是set testkey testvalue) $3 // 第一個字段占3B set // 第一個字段名:set $7 testkey $9 testvalue
-
- “寫后日志”的原因
- Redis記錄AOF日志時不會對命令進行語法檢查(節省檢查開銷)
- 基於第一點,采用“寫后日志”防止記錄錯誤命令
- AOF日志在主線程中執行
- AOF不會阻塞當前寫操作(先執行命令,后記錄日志)
- AOF潛在風險:
- AOF存在阻塞下一個操作的風險(下個操作執行之前主線程寫上一個操作的日志)
- 若Redis直接用作數據庫,命令執行后系統宕機——AOF日志沒記錄導致數據丟失
以上的AOF潛在風險都與AOF日志寫盤時間相關,解決方案——AOF三種寫回策略
2. AOF日志三種寫回策略——appendfsync參數的三個可選項
Always——同步寫回:每個寫命令執行后,同步寫磁盤
Everysec——每秒寫回:日志暫時寫到AOF日志cache,每隔1s寫盤
No——操作系統控制的寫回:日志暫時寫到AOF日志cache,由OS決定何時寫盤
配置項 | 寫回時機 | 優點 | 缺點 | 適用場景 |
---|---|---|---|---|
Always | 同步寫回 | 可靠性高 數據基本不丟失 |
每個寫操作都伴隨寫盤,性能影響較大 | 高可靠性 |
Everysec | 每秒寫回 | 性能適中 | 宕機時丟失1s內數據 | 允許少量數據丟失,同時性能影響較小 |
No | OS控制寫回 | 性能好 | 宕機時丟失數據較多 | 高性能 |
QA
Q: AOF文件過大帶來的一系列性能問題?如何控制AOF文件過大?
A: 性能問題
- 文件系統本身文件大小的限制
- 文件太大時,追加命令記錄效率變低
- 宕機后,AOF文件中的命令挨個重新執行的導致的故障恢復過程緩慢
解決方案:AOF重寫機制
3. AOF重寫——避免AOF日志過大
- AOF重寫:Redis根據數據庫現狀,創建一個新的AOF文件
- 操作:將當前Redis每個KV都用一條set命令寫入AOF重寫日志
- 原理:“多變一”——某個KV被多條命令反復修改
- AOF重寫是否會阻塞主線程?AOF重寫機制。
- AOF日志由主線程寫盤
- AOF重寫日志由后台子進程bgrewriteaof執行
- 重寫過程——“一個拷貝,兩處日志”
- “一個拷貝”:主線程fork bgrewriteaof子進程,通過拷貝頁表(OS的“寫時復制”原則)訪問主線程的內存數據
- “兩處日志”:寫操作發生時,AOF日志與AOF重寫均先將操作記錄到各自日志cache中,隨后fork bgrewriteaof子進程進程重寫日志操作
- AOF非阻塞的重寫過程
結尾
AOF故障恢復需要運行所有操作記錄,即“重放”過程很慢,既能避免數據丟失,又能更快恢復數據的方法——“RDB快照”
圖片來源於極客時間專欄《Redis核心技術與實戰》