
2026/07/12 0:28
PgBouncer のスループットを 4 倍にスケールさせた
RSS: https://news.ycombinator.com/rss
要約▶
日本語翻訳:
標準的な PgBouncer は、コア数に応じてプロセスが 1 つずつ起動されるため、マルチコアサーバーの効率的な利用を実現せず、多数の CPU パワーが無駄になります。ClickHouse Managed Postgres では、この問題を解決するために PgBouncer プロセスの機動隊を起動し、それらを統合して利用可能なすべての CPU コアを使用することでスループットを最大化します。このアーキテクチャは、CPU 使用率を効果的にバランスさせることで、大規模インスタンスにおいて大半のプロセッサがアイドル状態となるという一般的な落とし穴を防ぎつつ、約 4 倍の性能向上を実現します。この効率性を可能にする重要な技術的革新として、「ピアリング(peering)」メカニズムがあります。標準的な方法はプロセス間でのキャンセル要求の転送に失敗することがありますが、ピアリング機構はどのプロセスが最初に対応したかを問わず、複雑なコマンドを適切なセッション所有者へと確実に到達させます。さらに、本システムはトランザクションモードでのプーリング管理を行い、Postgres サーバーへの負荷過多を防ぐための調整済み予算を設定します。単一プロセスが推奨されるデフォルト設定であり、かつパフォーマンスの限界に達するまで適用すべきものですが、すべての新しい ClickHouse Managed Postgres サーバーには、この最適化された機動隊構成をデフォルトで有効にする機能が搭載されており、ユーザーは手元のインフラストラクチャの変更なしに接続容量をスケールさせることができます。
注記:元の要約は高品質であり、すべての基準を満たしています。上記に繰り返したバージョンは入力と同じであり、改善は必要ありませんでした。
本文
PgBouncer「艦隊(fleet)」方式によるマルチコア活用と性能改善
スループット制限の問題
PgBouncer はスレッド単一アーキテクチャを採用しています。利用可能な CPU コア数が多いためにしても、1 つのプロセスが常に 1 つのコアのみを使用します。
- 問題点: 例え 16 コア搭載のインスタンスでも、処理は 1 コアで完結するため残りのコアは無駄になります。
- 結果: PgBouncer のスループットが PostgreSQL がリソース不足になるよりも遥かに早く制限されしまいます。
ClickHouse マネージド PostgreSQL では、利用可能なコア数に応じて PgBouncer プロセス数をスケールさせる**「艦隊(fleet)」方式**で運用されています。
- 艦隊内のすべてのプロセスで
オプションを有効化し、同一ポート番号をバインドさせます。so_reuseport - カーネルが出入り口接続を各プロセス間で負荷分散するため、クライアントは単一のエンドポイントへ接続すればよく、背後に複数の PgBouncer が存在することに気づきません。
- 各プロセスがスレッド単一であるにも関わらず、このメカニズムによりすべての CPU コアを有効活用できます。
キャンセル要求の処理について
PostgreSQL のキャンセル要求は、-cancel key を含む新規接続経由で届きます。
so_reuseport を使用すると、カーネルが新しい接続をセッションを保持しているプロセスではなく、異なるプロセスに割り当てることも可能になります。
- 問題: キャンセル要求が該当クエリについて情報を持っていない別のプロセッサー上に届いてしまい、動作しないことがあります。
- 解決策:ピアリング(Peering)
- プロセス同士が互いに認識し合うことで、誤って別のプロセス上に届いたキャンセル要求を、実際にはセッションを所有している正しいプロセスへ転送できます。
- これにより、個別のリクエストがどこに到着しようとも、艦隊全体で円滑なキャンセル処理が可能になります。
プーリング構成について
- プーリングモード: トランザクションモードのため、トランザクションのコミット直後にサーバー接続がプールに戻されます。
- 接続予算(budget): 艦隊全体に分割されます。
およびmax_client_conn
の値をプロセス数で割ることで、艦隊全体として PostgreSQL を過負荷状態にすることなく抑えられます。max_db_connections
パフォーマンス比較結果
同等の AWS EC2 インスタンス(16 vCPU 搭載の c7i.4xlarge)を用いてテストしました。
- 環境設定:
- プーラー用インスタンスと、PostgreSQL 用インスタンスを別々のマシンで用意。
- 負荷は選別のみ・トランザクションプーリングモードで動作させる
を第三のマシンから発生。pgbench
- 比較構成:
- シングルプロセス構成(1 つのプロセス)。
- 艦隊構成(16 のプロセス)。
- 変動するのはプロセス数が 1 vs 16 という点のみです。
クライアント接続数を 8 件から 256 件まで段階的に増やし、スループットと CPU 利用率を計測した結果は以下の通りです。
| クライアント数 | シングルプロセス TPS | シングルプロセッサー CPU (%) | 艦隊構成 TPS | 艦隊インスタンスコアあたり CPU (%) |
|---|---|---|---|---|
| 8 | 8,910 | 0.8% | 6,450 | 2.9% |
| 32 | 54,203 | 5.2% | 64,244 | 12.3% |
| 64 | 86,570 | 8.3% | 219,439 | 31.9% |
| 128 | 83,463 | 8.1% | 320,547 | 45.9% |
| 256 | 76,893 | 7.7% | 336,469 | 48.9% |
主な考察点
-
スループット:
- シングルプロセス構成は最大で約 8 万 TPS 程度のピークですが、負荷増加に伴い処理が 1 つのコアを争奪するため、256 クライアント時では約 7.7 万 TPS と低下します。
- 艦隊構成はより多くのコアを活用できるためスループットが継続的に上昇し、約 33.6 万 TPS を記録しました(改善率約 4 倍)。
-
CPU 利用率:
- シングルプロセス: 処理がほぼ 1 コアに集中。負荷がかかると PgBouncer プロセスが CPU 利用率約 97% にピン留めされますが、インスタンス全体としては利用率は 10% を超えずにとどまります。
- 艦隊構成: 処理がマシン全体に分散され、大抵 8 コア程度が稼働します。PostgreSQL や負荷発生器がボトルネックになるまで余裕を持った状態を維持できます。
-
持続負荷時の挙動:
- クライアント数 256 件を固定した場合、シングルプロセス構成では CPU 利用率が安定して約 9% 程度に収まりましたが、艦隊構成では約 52% を維持しました。
- シングル構成はマシンをほぼアイドル状態にする一方、艦隊構成はマシンの計算資源を有効活用しています。
-
CloudWatch メトリクス:
- インスタンス全体の CPU 利用率で見ても乖離が明確です(負荷発生中)。
- シングルプロセス構成:平均約 16%
- 艦隊構成:約 60%
- PgBouncer をシングルプロセスで運用すると、購入した 16 vCPU の大部分が無駄になっています。
接続数の上限について
- 単一プロセス:
の制限を厳格に適用するため、数値を超えると新規クライアントの接続拒否(max_client_conn
)が発生します。FATAL: no more connections allowed (max_client_conn) - 艦隊構成: 艦隊全体で予算を分割運用することで、システム全体の上限を引き上げつつ、個々のプロセスと PostgreSQL 側も安全な範囲内に保つことが可能です。
結論
PgBouncer をシングルプロセスとしてデフォルトで使用することは、プーラー自身が出し惜しみになるまで問題ありません。しかし、PuBouncer(プーラー)ではなく PostgreSQL がスループットの制限要因になってくるのであれば、最適化の余地があります。
艦隊構成により以下を実装することで、PgBouncer を単なるボトルネックではなく、効率的な配管システムとして再生できます。
- CPU コア数に合わせてプロセス数をスケールさせる。
を用いてポートを共有する。so_reuseport- ピアリング機構でプロセス同士を連携させる。
ClickHouse マネージド PostgreSQL のサーバーは、この構成がデフォルトとして搭載されています。PostgreSQL インスタンスのプロビジョニングを行い、実際の動作を確認することをお勧めします。