それが僕には楽しかったんです。

ミドルウェアとかやってます

Redis を Docker 環境でいい感じに使うためのメモ

はじめに

どうも、最近メイドインアビスが「ポップな絵柄で描かれたダークソウル」と聞いて見てみたら想像以上にダークソウルだったのではまりそうなけんつです。

結構、Redis をいい感じに docker-compose とかで使いたい時があるのでこの際にまとめてしまおうといったノリで書いていく。
絶対こういう設定を本番環境で使うべきではないと思う。あくまでも開発時に欲しい設定をまとめている。

前提として、ジョブワーカーの MQ に使う

環境

  • Redis 5.0.1
  • docker-compose version 1.23.0
  • docker 19.03.5

上での構築を前提としている。

データの永続化

Redis のデータ永続化には AOF と RDB というタイプが存在する。
AOF は fsync ポリシーを選択した上で使用される追記専用のログ。AOF で選択できる fsync ポリシーは以下の通り。

  • no: fsync を利用しない。OS が都度データをフラッシュする。
  • always: 追加に関するログが書き込まれる度に fsync を実行する
  • everysec: 毎秒無条件に fsync を実行する。

AOF が肥大化すると、Redis はバックグランドでリライトを行う。この時、新しいファイルにはその時点のデータ・セットを再現するために必要な最小限の手順を記録した情報が付与される。
この肥大化に関わる設定は auto-aof-rewrite-percentage, auto-aof-rewrite-min-size を設定することで定義出来る。

欠点としては、AOF は RDB*1 を利用して永続化するよりもファイルサイズが大きくなりやすい。
他には、fsync ポリシーによっては全体的な性能低下を招くことがある。反対に RDB では、書き込み負荷が高い場合でも最大レイテンシを保証することが出来る。そのため、AOF はパフォーマンスが要求されるような箇所に everysec で使われるべきではない。*2

普段 Redis を使うときはメッセージキューとして利用することが多く、キューのデータをロストすると困るため AOF でデータを永続化させている。
これがクエリのキャッシュだったりする場合は、そもそも永続化とかしなくてもよいかなと思う。

設定は以下の通り。

dir /data
appendonly yes
appendfsync everysec
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 8mb

dir でデータを保持するディレクトリを設定する。これは Redis の docker コンテナ*3を利用するとき、何故か /data がデフォルトで aof を吐く。
aof ファイルは 8mb*4を最小サイズとして aof ファイルサイズが倍増した段階でリライトするようになっている。これはキューを2つしか使わない場合が多いからこうなっている。

ログ

開発時に見たい情報が多々あるので、ログレベルも設定して置きたい。基本的には debug としている。
また、Redis では logfile "" がデフォルトとなっているためログは /dev/null に吐かれるらしい。*5
STDOUT にログが吐かれるので docker-compose 側で fluentd や syslog とかを使っても面白そうだけど今回はやっていない。

loglevel debug
logfile ""

メモリ周り

Redis は基本的にオンメモリ KVS のため、利用できる最大メモリ量や仮にメモリを確保できなくて書き込めない場合にどのような挙動をするか設定することができる。

メモリ解放ポリシーは以下の通り。

  • volatile-lru: 期限切れのものを LRU によって削除する
  • allkeys-lru: 全てのキーを対象に LRU に基づいて削除する
  • volatile-ramdom: 期限切れのキーをランダムに削除する
  • allkeys-random: 全てのキーをランダムに削除する
  • volatile-ttl: TTL を比較して小さい順に削除する
  • noeviction: 削除せずに書き込みエラーとして返す

ジョブワーカー用のキューを作ることがおおいので、どのようなポリシーであっても削除されるとジョブの情報が失われるので noeviction を設定する。

最大メモリ使用量は 100MB 程度としておく。あまり利用されてホストマシンに影響がでても困るので。

maxmemory 100mb
maxmemory-policy noeviction

おわりに

とりあえず開発用にいつも使いたい設定たちはこんな感じだろうか。
書いていてログ周りが docker 環境ではやや面倒くさいのでレプリケーションクラスタを組んだ時にでも fluentd か syslog を使っていい感じにするやつをまとめる

*1:リレーショナル・データベースのことではなく、Redis の永続化手法の一つ。

*2:と、思う。

*3:redis:latest で振ってくるもの

*4:Redis での 8mb は 1024 * 1024 * 8 byte。 8m だと 8 * 10^6 byte となる

*5:これ結構びっくりした