こんにちは。データ収集ツールFluentdのメンテナーの福田です。
今回の記事では、有名なインメモリデータベースであるRedisの障害調査を行った事例を紹介します。
また、この調査はクリアコードのFluentd法人様向けサポートサービスの一貫で実施したもので、 Fluentdとセットで周辺のフリーソフトウェアのサポートを実施した事例となっています。
Redisのトラブルシューティングや、クリアコードの法人様向けサポートサービスに興味のある方は、ぜひ本記事をご覧ください。
問題発生から調査実施までの経緯
今回のサポート事例は、お客様のRedisのシステムにおいてフェイルオーバー1が発生し、その原因を調査した、というものになります。
お客様はクリアコードのFluentd法人様向けサポートサービスをご利用いただいており、 Fluentdとセットで他のフリーソフトウェアについてもサポートをご提供しておりました。 今回はこのFluentdサポートの一貫としてRedisの調査もできないかとご相談いただき、実施することとなりました。
また、Redisについてはこれまでのサポート実績がなく知見がなかったため、1からの調査となります。 そのため通常よりも調査に時間がかかる可能性があることを事前にお伝えし、ご了承いただいた上で調査を開始しました。
Redis Clusterのフェイルオーバー
今回の事例では、Redis Clusterという機能のフェイルオーバー1が発生しました。
Redis Clusterは、複数のRedisノードを並列稼働させてスケールさせることができます。 その際、特定のノードで障害が発生しても、フェイルオーバーをして処理を継続できるようにします。 例えば、あるマスターノードで障害が発生しても、対応するレプリカノードがマスターノードに切り替わって処理を継続できます。
今回の事例ではこのフェイルオーバーが発生したため、その障害原因を調査して明らかにしました。
調査結果: 負荷の高いコマンドの手動実行が原因
結論から言うと、負荷の高いコマンドを手動実行したことがフェイルオーバーの原因でした。
例えばKEYSコマンドは、ドキュメントに書いてある通り、大きなデータベースに対して実行するとパフォーマンスに致命的な影響を及ぼすため、本番環境での実行には注意が必要です。
Warning: consider KEYS as a command that should only be used in production environments with extreme care. It may ruin performance when it is executed against large databases.
このような負荷の高いコマンドの手動実行により高負荷がかかり、マスターノードが一時的に応答不能になりました。 こうしてマスターノードの応答が途絶えたのでフェイルオーバーが発動した、というのが今回の障害の経緯であったことを突き止めることができました。
補足: 対策
Redisのコマンドは、使い方によってはこのような障害を招く可能性があるので、注意が必要です。
対策としては、事前にドキュメントを確認するとよさそうです。
例えば、負荷の高いコマンドの例として挙げたKEYSコマンドについては、 代替策としてSCANやsetsも検討するように記載されています。
If you're looking for a way to find keys in a subset of your keyspace, consider using SCAN or sets.
調査方法
どのように原因を突き止めたのかを簡潔に紹介します。
また、調査に役立った情報も紹介します。
調査に役立つ情報
コマンドラインインタフェース: redis-cli
redis-cliコマンドを使うことで、Redisの各コマンドを実行できます。
次のコマンドがトラブルシューティングに役立ちました。
- redis-cli info
- Redisのバージョン情報からメモリーやCPU消費に関する情報まで、重要な情報を多く得られます。
- redis-cli cluster info
- 本事例のようにRedis Clusterの機能を使っている場合、クラスターに関する主要な情報を得られます。
- redis-cli config get *
- 設定値の一覧を確認できます。
- redis-cli memory doctor
- メモリーに関する問題について診断結果を得られます。
Redisの出力ログ
いつどのノードの応答が途絶えたのか、などが分かります。
特定のノードの応答が途絶えたログ例:
FAIL message received from {ノードの応答断絶を発見したノードのID} about {応答が途絶えたノードのID}
Marking node {応答が途絶えたノードのID} as failing (quorum reached).
Redis Clusterの機能を使っている場合は各ノードがIDで表現されるので、redis-cli cluster nodesコマンドを実行してIDを確認してください。 もしコマンドを実行できない状況でも、頑張って各ログの因果関係を追えば、ノードとIDの対応をパズルのように特定できます。
Docker Hubの公式イメージ
公式のDockerイメージを使って、すぐに簡単な動作確認を行うことができます。
RedisのDockerコンテナを起動:
# 必要に応じてタグを指定してください(例: v6を使うなら「redis:6」)
docker container run --rm -it --name redis-test redis
起動したコンテナに入って操作を行う:
# 別のシェルで
docker container exec -it redis-test bash
大きいメモリーピークが瞬間的に発生したことを確認
本事例では、次の各値から大きいメモリーピークが瞬間的に発生したことが分かりました。
- redis-cli info
used_memory_peak
(used_memory_peak_human
)- ピーク消費メモリーです。
- 本事例では、大きなメモリーピークの発生を確認できました。
- redis-cli config get *
maxmemory
- 消費するメモリー上限の設定値です。
- 消費メモリーがこの値を超えると、Key evictionの仕組みによって、消費メモリーがこの値を下回るまでデータを削除します。
- 本事例では、この値を大きく超える
used_memory_peak
が記録されていたことから、Key evictionが間に合わないくらい瞬間的に大きなメモリー負荷が生じたことが分かりました。
redis-cliプロセスがメモリーピークの原因であったことを確認
ログの調査からノードの応答が途絶えた時刻が分かっていたため、その時刻付近のプロセスの情報を調べました。
ちょうど応答断絶の直前にredis-cli
プロセスが誕生し、その直後にRedisの消費メモリーが急上昇していたことが分かりました。
このことから、redis-cliコマンドで負荷の高いコマンドを実行したことで、急激なメモリー負荷がノードにかかり、ノードが一時的に応答不能になった、という可能性が濃厚となりました。
そして、実際に負荷のかかるコマンドが実行されていた、ということが分かったため、これが原因であると断定することができました。
補足: Redisのライセンス変更とValkey
Redisはバージョン7.4からソースアベイラブルライセンスに変更し、フリーソフトウェア(オープンソース)ではなくなりました。 (今回の事例のRedisは、7.4よりも前のバージョンでした)。
クリアコードはフリーソフトウェアの発展に寄与することを理念としています。 Redisに代わるフリーソフトウェアのインメモリデータベースとしては、Valkeyがあります。 このValkeyのバージョン8.0においては、マルチコアのノードの性能がRedis v7の2倍以上になる、という話もあります2。 これらを踏まえ、今後はRedisからValkeyへの移行などもサポートしていけたらと思っています。
まとめ
本記事では、有名なインメモリデータベースであるRedisの障害調査を行った事例について紹介しました。
この調査はクリアコードのFluentd法人様向けサポートサービスの一貫で実施したもので、 Fluentd単体に限らず、このようにFluentdとその周辺のフリーソフトウェア(K8s, nginx, Embulkなど)をセットでサポートする事例やご相談もあります。
もしFluentdとその周辺のアプリケーションの運用でお困りのことがありましたら、 ぜひお問い合わせフォームからお気軽にご相談ください。
-
フェイルオーバー: 稼働中のシステムに障害が発生した際に待機中のシステムに切り替えることで、なるべくシステムが止まらないようにすること。 ↩
-
Valkeyのバージョン8.0の性能が従来の2倍以上に: https://www.publickey1.jp/blog/24/redisdbvalkey2.html ↩