AOF 是什麼
Append Only File
,通過保存 Redis 服務器所執行的命令來記錄數據庫狀態。
AOF 持久化的實現
命令追加
服務器在執行完一個寫命令後,會以協議格式將被執行的寫命令
追加到服務器狀態的 aof_buf 緩衝區
的末尾:
struct redisServer {
……
// AOF 緩衝區
sds aof_buf;
……
}
AOF 文件的寫入和同步
AOF 文件的載入和數據還原
流程:
AOF 重寫
爲什麼需要重寫
AOF 持久化是通過保存被執行的寫命令來記錄數據庫狀態的,隨着服務器運行時間的流逝,AOF 文件的內容會越來越多,文件體積越來越大
。如果客戶端執行了下面的命令:
127.0.0.1:6379> set name yano
OK
127.0.0.1:6379> set name yano2
OK
127.0.0.1:6379> set name yano3
OK
那麼 AOF 文件就需要保存 3 條命令,不僅使保存的 AOF 文件體積變大,還使得 Redis 啓動時載入數據變慢。
什麼是重寫
AOF 文件重寫(rewrite
),創建新的 AOF 文件替代現有的 AOF 文件,新舊兩個 AOF 文件所保存的數據庫狀態相同,但新 AOF 文件不會包含任何浪費空間的冗餘命令,體積更小。
如何重寫
不是讀取和分析現有的 AOF 文件內容,而是直接從數據庫讀取值組成相應的命令 AOF 文件。
AOF 後臺重寫
爲什麼需要後臺重寫
重寫函數 aof_rewrite 會進行大量的寫入操作,執行這個函數的線程會被長時間阻塞,但是 Redis 服務器使用單個線程來處理命令請求,如果直接在主線程直接更新,在重寫期間,服務器將無法處理客戶端發來的命令請求。所以將 AOF 重寫程序放到子進程中執行。
帶來的問題
子進程在進行 AOF 重寫期間,服務器進程還需要繼續處理命令請求,新的命令可能對現有的數據庫狀態進行修改,導致服務器當前數據庫狀態和重寫後的 AOF 文件保存的數據狀態不一致。
AOF 重寫緩衝區
爲了解決這種數據不一致
的問題,Redis 設置了一個 AOF 重寫緩衝區
,在服務器創建子進程之後開始使用,當 Redis 服務器執行完一個寫命令後,同時將這個寫命令發送給 AOF 緩衝區
和 AOF 重寫緩衝區
:
當子進程完成 AOF 重寫工作後,它會向父進程發送一個信號,父進程在收到這個信號後,會調用一個信號處理函數:
- 將 AOF 重寫緩衝區的所有內容寫入新的 AOF 文件,這樣新 AOF 文件所保存的數據庫狀態就與服務器當前的數據庫狀態一致;
- 對新 AOF 文件改名,原子覆蓋現有的 AOF 文件,完成新舊 AOF 文件的替換。
下圖左邊是正常流程,右邊是 AOF 重寫期間的流程:
注意
在實際中,爲了避免在執行命令時造成客戶端輸入緩衝區的溢出,重寫程序在處理列表、哈希表、集合、有序集合可能帶有多個元素的鍵時,會先檢查鍵所包含的元素數量,如果元素數量超過了一個常量閾值,重寫程序會使用多條命令來記錄鍵的值。
實際例子
配置 redis.conf
文件,使用 AOF:
appendonly yes
appendfsync always
appendfilename "appendonly.aof"
dir ./
啓動 Redis server:
src/redis-server redis.conf&
啓動 Redis client:
src/redis-cli
設置 key:
127.0.0.1:6379> set name yano
OK
127.0.0.1:6379> set name yano2
OK
127.0.0.1:6379> set name yano3
OK
查看 appendonly.aof 文件:
➜ redis-6.2.6 cat appendonly.aof
*2
$6
SELECT
$1
0
*3
$3
set
$4
name
$4
yano
*3
$3
set
$4
name
$5
yano2
*3
$3
set
$4
name
$5
yano3
參考鏈接
Redis 源碼簡潔剖析系列
Java 編程思想-最全思維導圖-GitHub 下載鏈接,需要的小夥伴可以自取~
原創不易,希望大家轉載時請先聯繫我,並標註原文鏈接。