サーバーに大量のイベントが流入し、平均して1秒あたり約1000イベント(ピークは〜2000)に対処しなければならない状況があります。
問題
私たちのシステムはHerokuでホストされ、比較的高価なHeroku Postgres DBを使用します。これにより、最大500のDB接続が可能になります。接続プーリングを使用して、サーバーからDBに接続します。
DB接続プールが処理できるよりも速くイベントが入ります
私たちが抱えている問題は、イベントが接続プールが処理できるよりも速く来るということです。1つの接続がサーバーからDBへのネットワークラウンドトリップを終了するまでに、n
追加のイベントが入るよりも多く、プールに解放されます。
最終的に、イベントは蓄積され、保存されるのを待機します。プールに使用可能な接続がないため、タイムアウトし、システム全体が動作不能になります。
クライアントから遅いペースで問題のある高周波イベントを発信することで緊急事態を解決しましたが、その高周波イベントを処理する必要がある場合にこのシナリオを処理する方法を知りたいです。
制約
他のクライアントがイベントを同時に読み取りたい場合があります
他のクライアントは、DBにまだ保存されていない場合でも、特定のキーを持つすべてのイベントの読み取りを継続的に要求します。
クライアントはGET api/v1/events?clientId=1
、クライアント1によって送信されたすべてのイベントを照会して取得できます。それらのイベントがまだDBに保存されていない場合でもです。
これに対処する方法に関する「教室」の例はありますか?
可能な解決策
サーバーのイベントをキューに登録します
サーバー上のイベントをキューに入れることができます(キューの最大同時実行数は400であるため、接続プールが不足することはありません)。
次の理由により、これは悪い考えです。
- 使用可能なサーバーメモリを使い果たします。スタックされたエンキューイベントは、大量のRAMを消費します。
- サーバーは24時間ごとに1回再起動します。これはHerokuによって課される厳しい制限です。イベントがエンキューされている間にサーバーを再起動すると、エンキューされたイベントが失われます。
- サーバーに状態が導入されるため、スケーラビリティが低下します。マルチサーバー設定があり、クライアントがキューに入れられたイベントと保存されたイベントをすべて読みたい場合、キューに入れられたイベントがどのサーバーに存在するかはわかりません。
別のメッセージキューを使用する
メッセージキュー(RabbitMQなど)を使用して、メッセージをポンプで送り、もう一方の端にはDB上のイベントの保存のみを処理する別のサーバーがあると仮定します。
メッセージキューがエンキューされたイベント(まだ保存されていない)のクエリを許可するかどうかわからないので、別のクライアントが別のクライアントのメッセージを読みたい場合、DBから保存されたメッセージとキューから保留中のメッセージを取得できますそれらを連結して、読み取り要求クライアントに返送できるようにします。
複数のデータベースを使用し、それぞれが中央のDBコーディネーターサーバーでメッセージの一部を保存して、それらを管理します
しかし、もう1つの解決策は、中央の「DBコーディネーター/ロードバランサー」で複数のデータベースを使用することです。イベントを受信すると、このコーディネーターはメッセージを書き込むデータベースの1つを選択します。これにより、複数のHerokuデータベースを使用できるようになり、接続の制限がデータベースの500倍になります。
読み取りクエリで、このコーディネーターはSELECT
各データベースにクエリを発行し、すべての結果をマージして、読み取りを要求したクライアントにそれらを送り返すことができます。
次の理由により、これは悪い考えです。
- この考えは...ええと..オーバーエンジニアリングのように聞こえますか?同様に管理するのは悪夢です(バックアップなど)。構築と保守は複雑で、絶対に必要でない限り、KISS違反のように聞こえます。
- 一貫性を犠牲にします。このアイデアを採用すれば、複数のDBでトランザクションを実行することはできません。
ANALYZE
クエリ自体を実行しましたが、問題はありません。また、接続プールの仮説をテストするためのプロトタイプを作成し、これが実際に問題であることを確認しました。データベースとサーバー自体は異なるマシンに存在するため、待ち時間が発生します。また、どうしても必要な場合を除き、Herokuをあきらめたくはありません。展開について心配しないことは、私たちにとって大きなプラスです。
select null
500接続で発行してみてください。接続プールが問題ではないことに気付くでしょう。