Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【ITニュース解説】How I Saved My System Through Peak Season

2025年09月21日に「Dev.to」が公開したITニュース「How I Saved My System Through Peak Season」について初心者にもわかりやすく解説しています。

作成日: 更新日:

ITニュース概要

ピーク時、システム遅延とOOM危機に直面。フロント最適化、Redis/OpenSearchによるバックエンド高速化、CQRS導入で乗り切った。監視・テストを徹底し、リアルタイム性やUXとのトレードオフを受け入れシステム安定稼働を実現。準備、根本原因特定、トレードオフ理解が重要だと説く。

出典: How I Saved My System Through Peak Season | Dev.to公開日:

ITニュース解説

システムの安定運用は、IT企業にとって最も重要な課題の一つだ。特に、年末年始やセール期間など、普段の何倍ものユーザーが殺到する「ピークシーズン」は、システムにとって最大の試練となる。ある会社の旅行予約システムも、まさにそんなピークシーズンを迎え、通常時の8〜10倍という想像を絶するアクセス集中に直面した。ダッシュボードを開くと、あらゆる操作が遅く、クリックするたびに大量のリクエストがサーバーに集中し、システム全体が重くなっていた。特に懸念されたのは、サーバーのCPUとメモリが過剰に使われ、「OOM(Out Of Memory)」と呼ばれるメモリ不足によるシステム停止が起こる可能性だった。この危機を乗り越えるため、システムを救うための戦いが始まった。

まず最初に行ったのは、ユーザーが直接触れる「フロントエンド」側の調査だった。Webブラウザの開発者ツール(F12キーで開くことができる)を使って状況を確認すると、数百ものデータ取得リクエストが絶え間なくサーバーに送られていることが分かった。これらのリクエストの多くは、顧客、取引、支払いといった大量のデータを丸ごと取得し、ダッシュボード上でリアルタイムに集計しようとしていた。その結果、ユーザーが何かをクリックするたびに、サーバーのCPUとメモリが急激に跳ね上がっていた。この問題に対し、すぐにできる対策として、重要度の低いデータは必要になった時に初めて読み込む「遅延読み込み(lazy loading)」を導入した。また、一部の変更頻度が低いテーブルデータをブラウザの「localStorage」という一時保存領域にキャッシュすることで、サーバーへのリクエスト数を減らした。これにより、ユーザー体験の滑らかさは多少犠牲になったものの、ダッシュボードの応答性は向上し、バックエンドの負荷も軽減された。しかし、これは問題の表面的な部分を解決したに過ぎないと理解していた。

次に、問題の根源である「バックエンド」側の調査に移行した。サーバーログを詳細に分析し、「APM(Application Performance Monitoring)」というアプリケーションの性能を監視するツールを使って、実行に時間のかかる「遅いクエリ」や、システムの状態を示す「プロファイリングメトリクス」を追跡した。その結果、多くのエンドポイントが、巨大なテーブルデータに対してリアルタイムで分析処理を行っていることが判明した。特に、データベースからデータを読み込む「読み込み集中型クエリ(read-heavy queries)」の多くが最適化されておらず、ダッシュボードが読み込まれるたびに全てのデータを取得していたため、CPUとメモリが限界まで使われていた。そこで、負荷の高い分析結果は、事前に計算しておき、高速なメモリデータベースである「Redis」に保存する手法を試した。最初は、ダッシュボードのデータがリアルタイムから数分遅れることに不安を感じたが、システムは安定し、ダッシュボードもスムーズに動作するようになった。これは、システムの安定性を保つために、リアルタイム性を一部犠牲にするという「トレードオフ」を受け入れた瞬間だった。Redisのキャッシュ利用率も向上し、一定の成果を感じた。

しかし、依然として読み込み集中型クエリはサーバーに大きな負荷をかけていた。データベースであるMySQLの性能を向上させるため、サーバーの台数を増やしたり、メモリを増設したりもしたが、メモリの急増は収まらなかった。そこで、より根本的な解決策として「CQRS(Command Query Responsibility Segregation)」という設計パターンを導入した。これは、データの書き込み処理と読み込み処理を分離するという考え方で、書き込みは従来のMySQLで行い、読み込みが集中する分析クエリには「OpenSearch」という検索や分析に特化したデータベースを利用することにした。これにより、データ同期のロジックが複雑になり、コードベースに含まれるサービスが増え、MySQL、Redis、OpenSearchそれぞれの監視も必要になったが、ダッシュボードは最終的に高速かつ安定して応答するようになった。重い分析テーブルがスムーズに動作するようになり、CPUとメモリが異常に跳ね上がることもなくなった。

最も重要な分析テーブルについては、リアルタイムで計算するとサーバーがクラッシュする危険性が高いため、完全に結果を事前計算してRedisに保存する方針を固めた。ピークトラフィック時でもダッシュボードは滞りなく動作し、以前のように数分遅れるチャートを見ることで、システムを安定させるためにはこのトレードオフが不可欠だったと改めて感じた。その結果、大量のデータエクスポートやダッシュボードのクエリはRedisから超高速でデータを返すようになり、CPU使用率は最大95%から60%にまで低下し、メモリも安定した。

ピークトラフィックの直前には、多くのユーザーが同じデータにアクセスしようとするため、多数の同時リクエストがRedisやデータベースに集中し、不安定になることがあった。この問題に対し、「Cache Promise」と「リクエスト結合(request coalescing)」という手法を導入した。これは、同じデータに対する複数のリクエストを一つにまとめ、実際にデータベースにアクセスするクエリを一度に限定するというものだ。これによりコードはより複雑になったが、バックエンドは安定性を保ち、まるで嵐を乗り越えたかのような感覚を得た。さらに、ピーク時以外にキャッシュを事前に温めておく「キャッシュの事前ウォームアップ(pre-warming cache)」ジョブもスケジュールした。これにより、ピーク時には既にデータがキャッシュされており、サーバーは8〜10倍のトラフィックも滞りなく処理することができた。

一部のExcelエクスポートや分析リクエストが、システム全体の重要な処理を遅らせる原因となっていた。そこで、「バルクヘッド」という、システムを複数の独立した区画に分け、一部の区画が過負荷になっても他の区画に影響を与えないようにする手法と、「リクエスト優先順位付け」を実装した。これにより、重要なリクエストが確実に先に処理されるようになり、一部の分析エクスポートは遅くなったものの、システム全体は応答性を保つことができた。また、OOM(メモリ不足)を避けるため、大量のエクスポートを行う際には、必要なフィールドのみをクエリするようにし、データを小さな塊に分けて処理する「バッチ処理」を導入した。ここでもリアルタイムデータの完全な正確性は一部犠牲になったが、サーバーは安定し、ダッシュボードもスムーズに動作し続けた。

準備期間中、システムの安定性を確保するため、継続的な監視体制を構築した。CPU使用率、メモリ使用率、Redisのヒット数、OpenSearchのクエリ応答時間、成功および失敗したリクエストの数など、様々なメトリクスを常にチェックした。そして、これらのメトリクスが事前に設定した危険な閾値を超えた場合には、すぐに警告が届くようにアラートを設定した。これにより、サーバーが完全に停止するまで待つことなく、メモリの急増や遅いクエリといった異常を即座に検知し、手遅れになる前に対応することが可能になった。

さらに、ピークシーズンが始まる前には、チームで「負荷テスト」と「カオスエンジニアリング」を実施した。負荷テストでは、ピーク時のトラフィックを人工的にシミュレーションし、システムがどこまで耐えられるかを確認した。カオスエンジニアリングでは、意図的にいくつかのサービスを停止させたり、故障させたりして、システムがそのような障害にどう反応するかをテストした。これらのテストを通じて、不要なキャッシュ、積もったリクエストキュー、OpenSearchの同期リスナーにおける潜在的なデッドロックなど、多くの問題点を発見した。これらの知見は、いざという時のロールバック計画を立てたり、サーバーのレプリカ数を増やしたり、バッチ処理のサイズを調整したりする上で非常に役立った。

ピークトラフィック真っ只中のある夜、事前計算されたダッシュボードに小さなバグが見つかり、データが通常よりも大幅に遅延する事態が発生した。この緊急事態に対応するため、本番環境で直接「ホットフィックス」を適用する必要があった。RedisやOpenSearchの状況を慎重に監視しながら、一つずつステップを踏んでデプロイ作業を進めた。非常に緊張し、ストレスの多い時間だったが、すべてが安定した時には、まさにデータの嵐を乗り越えたという大きな達成感があった。

この一連の経験から得られた教訓は非常に大きい。まず、「準備が全て」だということだ。事前に監視体制を整え、アラートを設定し、負荷テストやカオスエンジニアリングを実施し、キャッシュを事前ウォームアップしておくことで、成功と失敗の明暗が分かれることを痛感した。次に、「問題の根本原因を突き止めること」の重要性だ。表面的な症状だけを一時的に繕っても、読み込み集中型クエリ、最適化されていないエンドポイント、適切に同期されていないデータといった根本的な問題が解決されなければ、システムはいずれ破綻する。そして最後に、「完璧な解決策はない」という事実だ。ユーザー体験の滑らかさやリアルタイムデータの正確性を一部犠牲にしたり、システムの複雑さが増したりと、どのような選択にも必ず「トレードオフ」が存在する。これらのトレードオフを事前に認識し、計画に組み込んでおくことが、高負荷なピークシーズンにおいてシステムを安定稼働させるための鍵となる。

関連コンテンツ

関連IT用語