redis3.2のデータの永続化について設定ファイルをざっと読んだのでメモしておく。

redisには主に2つの永続化機能がある。

  • snapshot
    デフォルトで設定されているスナップショット機能。スナップショットの間隔を設定する。

  • append only file (AOF)
    書き込み操作を全てファイルに追記する。書き出す頻度を指定したり書き出しているファイルを再構成する機能なのがある。

以下調べた内容。

snapshot

$ vi /etc/redis/6379.conf
save 900 1
save 300 10
save 60 10000

save 秒 書き込み回数で設定が可能。デフォルトでは上記の3つの設定がされているので書き込みが無い場合はスナップショットを取らず1回でも書き込みが行われると15分に1回スナップショットが作成される。

$ file /var/lib/redis/6379/dump.rdb
/var/lib/redis/6379/dump.rdb: data

スナップショットはdump.rdbに出力され、バイナリっぽい内容が書かれている。再起動時にはこのスナップショットからデータを復元する。

append only file

Redisに書き込まれた内容をファイル(appendonly.aof)に書き出す設定を追加する。

$ vi /etc/redis/6379.conf
- appendonly no
+ appendonly yes

書き出す頻度の設定は次の3つから選べる。

# appendfsync always
appendfsync everysec
# appendfsync no

更新ごとにファイルへ書き出す。1秒毎にファイルへ書き出す。ファイルへ書き出さない。からファイルへ書き出す頻度が選べる。
更新ごとにファイルへ書き出す場合はディスクIOが発生するので当然遅くなる。RDBより遅くなることもあるらしい。オススメは毎秒書き出す設定とのこと。当然書き出さない設定は最速。fsyncは速くすることができないので、パフォーマンスを捨てるかデータを捨てるかを選択する事になりそう。

AOFの細かな設定

# BGSAVEかBGREWRITEAOFの実行中にはfsyncしない
no-appendfsync-on-rewrite no

# ログのサイズが指定したパーセンテージ分増えたらBGREWRITEAOFを実行してAOFを再構成する
auto-aof-rewrite-percentage 100

# 自動でAOFを実行しない下限サイズ
auto-aof-rewrite-min-size 64mb

# AOFから復旧したとき不要なAOFを消すかどうか
aof-load-truncated yes

BGSAVEは非同期でRDBファイルを生成するコマンド。BGREWRITEAOFはAOFファイルのサイズが肥大化した時にバックグラウンドで再構成するコマンド。

動作確認

dump.rdbがある同じディレクトリにappendonly.aofが出力されている。

$ ls -l /var/lib/redis/6379/appendonly.aof
-rw-r--r--. 1 root root 0 Oct 4 14:50 /var/lib/redis/6379/appendonly.aof

最初はファイルが空なのでデータをRedisに書き込む。

$ file /var/lib/redis/6379/appendonly.aof
/var/lib/redis/6379/appendonly.aof: empty
$ redis-cli -p 6379
127.0.0.1:6379> set "hoge" "hhhh"
OK
127.0.0.1:6379> exit

次の様に操作がappendonly.aofに追記されているのが確認できる。3ノードのクラスタで確認すると全てのノードのファイルに同じ内容が出力されていることが確認できる。

データを変更したりflushallしてみるとその操作がファイルに書き出されいていることが確認できる。

$ file /var/lib/redis/6379/appendonly.aof
/var/lib/redis/6379/appendonly.aof: ASCII text, with CRLF line terminators
$ cat /var/lib/redis/6379/appendonly.aof
(...)
set
$4
hoge
$4
hhhh
$ redis-cli -p 6379
127.0.0.1:6379> get hoge
"hhhh"
127.0.0.1:6379> set "hoge" "fuga"
OK
127.0.0.1:6379> get hoge
"fuga"
127.0.0.1:6379> exit
$ cat /var/lib/redis/6379/appendonly.aof
set
$4
hoge
$4
hhhh
*3
$3
set
$4
hoge
$4
fuga
$ redis-cli -p 6379
127.0.0.1:6379> flushall
OK
127.0.0.1:6379> exit
$ cat /var/lib/redis/6379/appendonly.aof
set
$4
hoge
$4
hhhh
*3
$3
set
$4
hoge
$4
fuga
*1
$8
flushall

3ノードすべてで同じファイルが生成され全ての操作が記録されていることが確認できた。

適当なデータを書き込んですべてのredisを停止した場合でもデータが再度読み込まれていることが確認できる。dump.rdbかappendonly.aofのどちらからから復元されたかはわからないがとりあえず復元されることが確認できた。

$ redis-cli -p 6379
127.0.0.1:6379> set "hoge" "0987"
OK
127.0.0.1:6379> set "fuga" "1234"
OK
127.0.0.1:6379> keys *
1) "fuga"
2) "hoge"
127.0.0.1:6379>

$ sudo /etc/init.d/redis_6379 stop
$ cat /var/lib/redis/6379/appendonly.aof
(...)
set
$4
hoge
$4
0987
*3
$3
set
$4
fuga
$4
1234
$ /etc/init.d/redis_6379 start
$ redis-cli -p 6379
127.0.0.1:6379> keys *
1) "hoge"
2) "fuga"

まとめ

appendfsync alwaysでどの程度性能が劣化するのかは気になるところ。appendfsync everysecがパフォーマンス的に良いとのことなのでやはり1秒間隔でデータを書き出し、1秒間のデータは失う可能性があるけどすごく速いという性質はキャッシュ用途で使うのが正解でしょうか。

終わり。