簡介
Redis是一個可以持久化的內存數據庫,也就是說redis需要經常將內存中的數據同步到硬盤來保證持久化。
redis支持兩種持久化方式:
snapshotting
(快照),也是默認的方式- append-only file (縮寫
aof
)的方式
snapshotting方式持久化數據
快照方式是redis默認的持久化方式。這種方式是將內存中的數據以快照的形式寫入二進制文件中,默認的文件名爲dump.rdb。後臺保存快照到磁盤會佔用大量內存,調用save保存內存中的數據到磁盤,將阻塞客戶端請求,直到保存完畢。可以通過配置文件設置自動做快照的持久化方式。調用shutdown命令,Redis服務器會先調用save,所有數據持久化到磁盤之後纔會真正退出。修改redis.conf:
save 900 1 #900s內如果超過1個key被修改,則發起快照保存
save 300 10 #300s內如果超過10個key被修改,則發起快照保存
save 600 10000 #600s內如果超過10000個key被修改,則發起快照保存
aof方式持久化數據
由於快照方式是在一定的時間間隔內做快照的,所以如果redis意外宕機的話,就會丟失最後一次快照後的所有修改。
aof比快照方式具有更好的持久化性,是由於在使用aof時,redis會將每一個收到的寫命令都通過write函數追加到文件中當redis重啓時會通過重新執行文件中保存的寫命令來在內存中重建整個數據庫的內容。aof最大的問題就是隨着時間append file會變的很大,所以我們需要 bgrewriteaof 命令重新整理文件,只保留最新的kv數據。
當然由於os會在內核中緩存write做的修改,所以可能不是立即寫到磁盤上,這樣aof方式的持久化還是有可能丟失部分的修改。
可以通過配置文件(redis.conf)告訴redis,我們想要通過fsync函數強制os將修改寫入到磁盤的時機:
appendonly yes #默認是關閉的,啓用aof持久化方式
#appendfsync always #收到寫命令就立即寫入磁盤,最慢,但是能夠保證完全的持久化
appendfsync everysec #每秒鐘寫入磁盤一次,在性能和持久化方面做了很好的折中
#appendfsync no #完全依賴os,性能最好,但持久化沒有保證
按照以上方式對redis設置進行修改之後,我們向數據庫寫入一些數據:
ubuntu@dbserver:/var/lib/redis$ redis-cli -a xxxxxx
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> set name zhangsan
OK
127.0.0.1:6379> hmset user:001 name xiaojuan age 23
OK
127.0.0.1:6379>
然後退出redis客戶端,我們將會看到剛纔我們的寫操作全部記錄到appendonly.aof文件中:
127.0.0.1:6379> exit
ubuntu@dbserver:/var/lib/redis$ ls
appendonly.aof dump.rdb
ubuntu@dbserver:/var/lib/redis$ sudo cat appendonly.aof
*2
$6
SELECT
$1
0
*3
$3
set
$4
name
$8
zhangsan
*6
$5
hmset
$8
user:001
$4
name
$8
xiaojuan
$3
age
$2
23
ubuntu@dbserver:/var/lib/redis$
自動的bgrewriteaof
爲了避免aof文件過大,我們會週期性的做bgrewriteaof來重整aof文件。以前我們會額外的配置crontab在業務低峯期執行這個命令,這額外的增加一個workaroud的腳本任務在大集羣裏是很糟糕的,不易檢查,出錯無法即時發現。
於是這個自動bgrewriteaof功能被直接加到redis的內部。首先對於aof文件,server對象添加一個字段來記錄aof文件的大小server.appendonly_current_size,每次aof發生變化都會維護這個字段。
bgrewriteaof完畢或者實例啓動載入aof數據後也會調用aofUpdateCurrentSize這個函數維護這個字段,同時會記錄下此時的aof文件的大小server.auto_aofrewrite_base_size作爲基準值,用於接下來判斷aof增長率。
有了當前值和基準值我們就可以判斷aof文件的增長情況。另外還需要配置兩個參數來判斷是否需要自動觸發bgrewriteaof。
auto_aofrewrite_perc: aof文件的大小超過基準百分之多少後觸發bgrewriteaof。默認這個值設置爲100,意味着當前aof是基準大小的兩倍的時候觸發bgrewriteaof。把它設置爲0可以禁用自動觸發的功能。
auto_aofrewrite_min_size: 當前aof文件大於多少字節後才觸發。避免在aof較小的時候無謂行爲。默認大小爲64mb。
兩個參數都是可以在conf裏靜態配置,或者通過config set來動態修改的。
redis 127.0.0.1:6379> config get auto-aof-rewrite-percentage
1) "auto-aof-rewrite-percentage"
2) "100"
redis 127.0.0.1:6379> config get auto-aof-rewrite-min-size
1) "auto-aof-rewrite-min-size"
2) "1048576"
redis 127.0.0.1:6379> config get auto-aof-rewrite-min-size
1) "auto-aof-rewrite-min-size"
2) "1048576"
redis 127.0.0.1:6379> config set auto-aof-rewrite-percentage 200
OK
redis 127.0.0.1:6379> config set auto-aof-rewrite-min-size 10485760
OK
然後就是觸發檢查的主邏輯,serverCron時間事件中每次都會檢查現有狀態和參數來判斷是否需要啓動bgrewriteaof。
如果aof文件增長百分率growth大於auto_aofrewrite_perc,則自動的觸發後一個bgrewriteaof。
注:從 Redis 2.4 開始, AOF 重寫由 Redis 自行觸發, bgrewriteaof 僅僅用於手動觸發重寫操作。