皆さんこんにちは技術統括本部IDMチームの木村です。
今回は、開発サーバで発生した"Redis::CommandError: LOADING Redis is loading the dataset in memory"に対応した話をしていきます。
こちらのRedisエラーは原因を端的に書いてしまうと、AOFファイルからデータの再構築を行っている最中にアクセスをしてしまったことで問題が起こっていました。
AOFは、Redisの永続化の仕組みのうちの一つで、Redisが受け付けた書き込みのログを保存しているファイルになります。サーバの起動時にこれを読み込むことでデータの復元が出来る様になります。
では実際にどの程度肥大化してしまったのかを調べてみました。docker systemコマンドを使ってディスクの使用量を確認してみると、なんと30Gほど使っていることがわかりました。
$ docker system df -v | grep opid_redis4w_data opid_redis4w_data 1 29.64GB
起動時に30GBものログファイルを解釈してredis上で実行している事がわかりました。確かにこれでは、データ再構築に時間がかかるのも納得です。
対策
待っていればいずれ使えるようにはなるのですが、とはいえ開発用のサーバで起きてしまうと困ってしまいます。 また、不整合が起こると大変なのでAOFファイルを消してしまうわけにもいかずという所で幾つか対策を試してみました。
対策:その1 docker-composeの起動順序を変えてみる
IDMチーム内の共有環境は、docker-composeで作成されています。新しく開発したソースをデプロイするには以下の手順で行ってます。
- docker-compose downで動いてるサーバを停止
- CIサーバで必要なソースをレポジトリから取得、capistranoを使ってデプロイ
- docker-compose buildでイメージを作成
- docker-compose upで起動する
このうち2と3の間にredisなどのミドルウェアを起動する様にしてみました。
- docker-compose downで動いてるサーバを停止
- CIサーバで必要なソースをレポジトリから取得、capistranoを使ってデプロイ
- redisや必要なミドルウェアを先に起動する
- docker-compose buildでイメージを作成
- docker-compose upで起動する
ただ、この施策はあまり効果がなく、開発環境が使えるまでの時間は短くなったものの結局エラーが発生してしまいました。
対策:その2 BGREWRITEAOF
を使ってAOFファイルを再生成する
そもそもログが30Gもあるのがおかしいと思ったため再生成ができないか調査してみました。
するとredis公式のドキュメントで、BGREWRITEAOF
というコマンドが紹介されていました。
ものは試しとredisの中に入りBGREWRITEAOFを実行してみた所、以下の様に実行できました。
~$ docker exec -it opid_redis_for_worker_1 /bin/sh /data # redis-cli 127.0.0.1:6379> BGREWRITEAOF Background append only file rewriting started 127.0.0.1:6379>
しばらく待ってからdockerコマンドで使用しているディスク容量をもう一度確認してみます。
$ docker system df -v | grep opid_redis4w_data opid_redis4w_data 1 682.2kB
ということで圧縮することができました。32GBから682kBへ省略ができたことがわかります。
起動直後にアクセスしても、エラーが発生しなくなりました。
まとめ
AOFファイルが肥大化してしまって、Redisサーバの起動に時間がかかるようになってしまった場合は、BGREWRITEAOF
を使うとAOFファイルを再生成することが出来るので、一度試してみてはいかがでしょうか。
最後に
OPTiMでは様々な分野で活躍できるエンジニアを募集しております。
興味がある方は是非弊社採用ページにてご覧ください!