はじめに
開発環境とステージング環境は、本番環境で直面する多くの状況を予測するのに役立ちますが、一部の課題は大規模環境で初めて表面化し始めます。データベース接続管理はまさにこのカテゴリに当てはまります。クライアントインスタンスからのリクエスト数は、データベースソフトウェアがサポートする接続制限をすぐに超える可能性があります。
長時間にわたるキュー時間、リクエストの失敗、およびユーザーに影響を与えるエラーを防ぐためには、このリソース競合に対処するために、接続管理ポリシーとツールが必要です。コネクションプーリングは、データベース接続を管理および再利用するための中間キューイングシステムを導入する戦略に基づいており、これらの問題を軽減するためにしばしば成功を収めています。
このガイドでは、コネクションプーリングとは何か、具体的にどのような状況に対処しようとしているのか、そしてどのように機能するのかについて説明します。代表的な例としていくつかの一般的な実装を紹介し、クライアントリクエストがデータベースの利用可能な接続数を上回った場合にクライアントがどのように動作を変化させるかについて説明します。
コネクションプーリングは、Prisma Accelerate が Prisma Data Platform 上で提供するコア機能の 1 つです。Prisma を使用してデータベースを操作している場合は、無料プロジェクトを開始して、接続を簡単に管理し、データを閲覧してください。
データベース接続を開くには何が必要ですか?
コネクション管理全般、特にコネクションプーリングについて説明する前に、データベース接続中に何が起こるのかを詳しく見てみましょう。
クライアントアプリケーションがデータベースへの接続を開くには、驚くほど多くのステップが必要です。各接続には、次のステップの一部またはすべてが発生する必要があります。
- データベースサーバーの IP アドレスを特定するために必要な DNS ルックアップ
- サーバーへの TCP 接続を確立するために必要な スリーウェイハンドシェイクの実行
- TLS ハンドシェイクを介した接続の暗号化のネゴシエーションと有効化
- セッションパラメータを確立するためのデータベースソフトウェアとの設定と要件の交換
- クライアントの ID を確立するためのデータベース認証チェックの実行
- クライアントが要求されたデータベースオブジェクトへのアクセス権を持っていることを確立するための初期認可チェックの実行
- 実際のクエリの実行と結果の返却
- データベースセッション、TLS 暗号化、および TCP 接続の切断
接続数がデータベースサーバーのリソースにどのように影響しますか?
上記のすべてを完了するために必要な時間に加えて、各接続は確立および維持するためにリソースも必要とします。たとえば、PostgreSQL では、一部のテスト済みワークロードでは、接続ごとに 1.5〜14.5MB のメモリが使用されました。
サーバーが新しい接続の状態を管理する必要があるため、CPU 使用率も接続数とともに上昇します。接続の管理に多くのメモリと CPU が使用されるにつれて、トランザクションの実行速度など、他のものに影響を与え始める可能性があります。多数の接続を管理するオーバーヘッドは、データベースシステムの最適な結果のキャッシュ能力を妨げ始め、有用な作業を実行する能力を低下させます。
接続数がクライアントアプリケーションにどのように影響しますか?
上記の段落では、データベースサーバーが支払う必要のある接続のコストについて説明していますが、クライアントへの直接的な影響もあります。データベースサーバーは、特定の数の接続を受け入れるようにのみ構成できます。その制限に達すると、追加の接続リクエストは拒否されます。
つまり、デフォルトでは、クライアントコードは、これらの障害を処理するために指数バックオフアルゴリズムを使用してリクエストを繰り返すロジックを実装する必要があります。しかし、さらに重要なことは、クライアントがその機能を頻繁に使用することを余儀なくされ、クエリの停滞、遅延、およびユーザーにすぐに波及する可能性のある問題につながる可能性があることです。
仲介する中間コンポーネントがない場合、次のことを検討する必要があります。
- データベースサーバーの接続制限を増やす(データベースサーバーのメモリと CPU 使用率、およびトランザクションレートに影響を与える)、
- データベースをスケールアップして、より多くのメモリ、CPU、またはネットワーク容量を割り当てるか、
- データベースをスケールアウトして、より多くのマシンにリクエストを分散させる
これらの選択肢はそれ自体が必ずしもネガティブなわけではありませんが、ここで説明している種類の輻輳に対しては過剰になる可能性があります。コネクションプーリングは、現在持っているリソースをより有効活用するのに役立つ代替手段です。
コネクションプーリングとは何ですか?
コネクションプーリングは、クエリが解決されたときにすぐに接続を閉じるのではなく、複数のリクエストに対してデータベース接続を再利用する戦略です。通常、これは、データベースサーバーとそのクライアントアプリケーションの間で、両者間の接続を管理する役割を担うコネクションプーラーと呼ばれるソフトウェアを導入することによって行われます。
前述のように、接続を確立する際には、クエリが実際にデータベースサーバーによって実行される前に、かなり長い一連の操作を実行する必要があります。コネクションプーラーは、最初のクエリの後に接続を開いたままにし、追加のクエリを実行するために再利用することで、これらの操作のコストを償却しようとします。
このシステムでは、クライアントはデータベースに直接接続するのではなく、コネクションプーラーに接続します。クライアントはプーラーをデータベース自体として扱い、プーラーはクエリを解釈して適切な接続をクライアントに渡します。注意すべき点の 1 つは、クライアントとプーラー間の接続を開閉する際にもオーバーヘッドが依然として発生することです。ただし、これらの接続は、データベース自体への接続を確立する際に大部分の負荷の高いプロセスが発生するため、通常はオーバーヘッドが低くなります。
コネクションプーリングはどのように機能しますか?
コネクションプーラーは、クライアントに代わってデータベースへの接続を開き、閉じ、維持する役割を担います。これは、キャッシングシステムが使用する可能性のあるアルゴリズムと同様のアルゴリズムに従って行われます。
クライアントがコネクションプーラーに接続して接続をリクエストすると、プーラーはリクエストの特性をすばやく評価します。データベースユーザー、実行される特定の操作、暗号化のタイプ、またはアクセスされるデータベースオブジェクトなどの情報を調べることがあります。
この情報を取得すると、利用可能な接続のプールを見て、新しいリクエストを実行するために使用できる既存の接続があるかどうかを確認します。適切な利用可能な接続が見つかった場合は、それをクライアントに渡し、接続を介してクエリを実行できるようにします。新しいリクエストの実行に適した接続がプールに存在しない場合は、必要なパラメータを使用してデータベースへの新しい接続を開き、代わりにそれをクライアントに渡します。
クライアントは通常どおり接続を使用してクエリを実行します。クエリが完了すると、接続を終了する代わりに、プーラーは接続をプールに戻し、後続のクエリで再利用できるようにします。プーラーは、選択したアルゴリズム(確立からの時間、最後の使用からの時間など)を使用して、プール内の接続を非同期的にガーベジコレクションできます。
内部プーリングと外部プーリングの違いは何ですか?
大まかに言えば、コネクションプーリングとは、複数のリクエストにわたって接続を維持するアルゴリズムを指します。これは、クライアントアプリケーション内で内部的に実装することも、外部ツールまたはサービスを使用して外部的に実装することもできます。
コネクションプーリングの内部実装は、多くの場合、データベースドライバ、ORM(オブジェクトリレーショナルマッパー)、またはクライアントアプリケーションに組み込まれる可能性のあるその他のデータベースクライアントの機能です。これらのソリューションは、データベースサーバーへの長時間実行接続を維持し、コードベース内の複数のクエリに再利用することで、コネクションプーリングの利点の一部を提供します。
内部コネクションプーリングは便利ですが、実用的な制限がいくつかあります。実行されているアプリケーションの各インスタンスは、通常、独自のプールを維持する必要があります。これは、各プールが単一のアプリケーションインスタンスのみにサービスを提供するため、接続をクエリ間でどの程度広く共有および再利用できるかに影響します。
代替ソリューションは、外部コネクションプーリングを実装することです。このアプローチでは、複数のクライアントインスタンスの接続を通信およびプールできる独立したソフトウェアを展開します。このデプロイメントシナリオでは、追加のネットワークホップが導入されますが、通常は追加のスケーラビリティと柔軟性が提供されます。コネクションプーラーは、多くの異なるクライアントにサービスを提供するためにデータベースサーバーと一緒にデプロイすることも、単一のサーバーで実行されているアプリケーションインスタンスにサービスを提供するためにクライアントアプリケーションと一緒にデプロイすることもできます。
一般的な外部コネクションプーラーにはどのようなものがありますか?
さまざまなデータベースシステムで利用できるコネクションプーラーが多数あります。PostgreSQL で利用可能な実装をいくつか見て、さまざまなソリューションが問題にどのようにアプローチしているかをより深く理解できます。
pgbouncer
おそらく、PostgreSQL で最もよく知られているコネクションプーラーは pgbouncer
です。
2007 年に作成された pgbouncer
は、PostgreSQL 接続を管理するための軽量なプーリングメカニズムを提供することに重点を置いています。デプロイ場所とプーリングの正確な実行方法の両方に関して、優れた柔軟性を提供します。
クライアントからの接続が短寿命である状況では、プロジェクトは、クライアントコードが実行される Web サーバーに pgbouncer
をデプロイすることを推奨しています。プーラーをクライアントソフトウェアと一緒に配置すると、両者間の接続で TCP よりも軽量なメカニズムを使用できるようになり、レイテンシが削減されます。多数の異なるクライアントからの接続をまとめてプールする必要があるシナリオでは、代わりにデータベースサーバーと一緒にデプロイできます。
pgbouncer
を使用する際の最も重要な決定事項の 1 つは、使用するプーリングモードを選択することです。利用可能な 3 つのオプションは次のとおりです。
- トランザクションプーリング:クライアントによるすべてのトランザクションの後に接続が取り消されます。後続のトランザクションの場合、接続が再度割り当てられます。これにより、
pgbouncer
は、クライアントがトランザクション間で他の操作を実行している間、接続を迅速に再利用できます。 - セッションプーリング:接続は、プーラーとのクライアント接続の期間中、クライアントに割り当てられます。つまり、各クライアント接続は、データベースへの専用接続とペアになっています。接続はクライアントセッションが終了すると再利用されますが、プーラーを一度に使用できるクライアントの数は大幅に減少します。
- ステートメントプーリング:接続は、個々のステートメントを実行するために割り当てられます。これにより、接続の迅速な割り当てと割り当て解除が行われ、多数のクライアントが限られた数の接続を使用できるようになりますが、トランザクションセマンティクスが損なわれ、場合によっては予期しない動作につながる可能性があります。
ほとんどの場合、トランザクションプーリングは、アイドル接続のリサイクルの点で最適なバランスを提供し、適切な数のクライアントを管理し、データベースセッションとトランザクションセマンティクスに関する予期される動作を維持します。
pgpool
別の PostgreSQL コネクションプーラーは pgpool-II
であり、多くの場合 pgpool
と呼ばれます。pgbouncer
はコネクションプーリングのみに焦点を当てた軽量ツールですが、pgpool
はより多くの関連機能を提供します。
コネクションプーリングに加えて、pgpool
は、多数のバックエンドデータベースインスタンス間でクエリの負荷分散をサポートし、自動フェイルオーバーのための高可用性動作を可能にするウォッチドッグサービスを備えています。さらに、特定のデプロイメントシナリオで非常に役立つ可能性のある管理 GUI が提供されます。
これらの高度な機能にもかかわらず、pgpool
は通常、コネクションプーリングの実際の管理に関してはやや制限があると考えられています。pgbouncer
は 3 つのプーリングモードを許可していますが、pgpool
はセッションモードと同等のモードでのみ動作できます。つまり、接続はクライアントが切断された場合にのみ再割り当てされます。これにより、pgpool
が処理できるクライアントの数が減少します。
結論
このガイドでは、コネクションプーリングの概念と、それがデータベースの負荷とリソース消費を削減するためにどのように使用できるかを見てきました。クライアントとデータベース間の接続の確立にコストがかかる理由のいくつかを概説し、接続を再利用することで後続のクエリのコストを削減する方法について説明しました。その後、コネクションプーラーが実際にどのように機能するかについて説明し、PostgreSQL エコシステムからのプーラーの代表的な例をいくつか見てきました。
アプリケーションがスケールし、クエリ負荷が複雑になるにつれて、データベース接続の制限はすぐに問題を引き起こす可能性があります。接続管理に関連するオーバーヘッドを完全に取り除くことは不可能ですが、コネクションプーラーは、パフォーマンスを維持し、データベースが処理できるクライアントの数を増やすための非常に貴重なツールです。
コネクションプーリングは、Prisma Accelerate が Prisma Data Platform 上で提供するコア機能の 1 つです。Prisma を使用してデータベースを操作している場合は、無料プロジェクトを開始して、接続を簡単に管理し、データを閲覧してください。