PostgreSQLでプールサイズとデータベース接続のスイートスポットを決定する方法


14

データベースサーバーへのピーク時にトラフィックを処理できません。ハードウェアの改善を検討しています(その点についてはこの質問をご覧ください)が、プーリング構成とサーバーの調整にも取り組みたいと考えています。

私たちが取り組んでいるアプリケーションは、スマートフォン向けのターンベースのマルチプレイヤーゲームです。バックエンドは、ユニコーンPostgreSQL 9.1をデータベースとするRailsで構成されています。現在、登録ユーザーは60万人で、ゲームの状態はデータベースに保存されているため、数秒ごとに数千の書き込みが行われます。PgBadgerを使用してPostgreSQLのログファイルを分析しましたが、重要な時間帯に大量の

FATAL: remaining connection slots are reserved for non-replication superuser connections

この問題に対処するための単純な解決策は、postgresql.confのmax_connections(現在は100) を増やすことです。私はhttp://wiki.postgresql.org/wiki/Number_Of_Database_Connectionsを読みましたが、これはこれが正しいことではないかもしれないことを示しています。前述の記事では、max_connectionsとpool sizeの間のスイートスポットを見つけることに言及しています

このスイートスポットを見つけるために何ができますか?max_connectionsプールサイズの異なる値のI / Oパフォーマンスを測定するための優れたツールはありますか?

現在の設定では4台のゲームサーバーがあり、各サーバーにはユニコーンワーカーが16人、プールサイズが5です。

以下は、使用しているデフォルト以外のpostgres-settingsです。

version                      | PostgreSQL 9.1.5 on x86_64-unknown-linux-gnu,compiled by gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3, 64-bit
checkpoint_completion_target | 0.9
checkpoint_segments          | 60
checkpoint_timeout           | 6min
client_encoding              | UTF8
effective_cache_size         | 2GB
lc_collate                   | en_US.UTF-8
lc_ctype                     | en_US.UTF-8
log_destination              | csvlog
log_directory                | pg_log
log_filename                 | postgresql-%Y-%m-%d_%H%M%S.log
log_line_prefix              | %t
log_min_duration_statement   | 200ms
log_rotation_age             | 1d
log_rotation_size            | 10MB
logging_collector            | on
max_connections              | 100
max_stack_depth              | 2MB
server_encoding              | UTF8
shared_buffers               | 1GB
ssl                          | on
TimeZone                     | localtime
wal_buffers                  | 16MB
work_mem                     | 8MB

過去数週間にメーリングリストでこれについて尋ねていた人ですか?もしそうなら、その議論にバックリンクを追加します。また、DBサーバーのハードウェアと構成は何ですか?wiki.postgresql.org/wiki/Slow_Query_Questions。デフォルト以外の設定を含める:wiki.postgresql.org/wiki/Server_Configurationをwiki.postgresql.org/wiki/Tuning_Your_PostgreSQL_Serverを読みましたか?可能な場合、より大きなトランザクションにバッチ処理しますか?キャッシングレイヤーを使用していますか?synchronous_commit = offまたはを使用していcommit_delayますか?
クレイグリンガー

PostgreSQLサーバーに合計20の接続がありますか?ゲームサーバーあたり5 各ゲームサーバーからの5つの接続は、16人のユニコーンワーカー間で共有されていますか?
クレイグリンガー

ああ、遅いクエリを記録していますか?もしそうなら、あなたのホットスポットは何ですか?シンプルなINSERT?スキーマはどのようなものですか?パーティション化されていますか?何explain analyzeいくつかのサンプルクエリの?チェックポイントの頻度と所要時間はどれくらいですか?(チェックポイントロギングオプションを参照)。そして真剣に、あなたのPostgreSQLのバージョンは何ですか?(更新:ここにハードウェアをリストしているようです:dba.stackexchange.com/questions/28061/…
クレイグリンガー

とにかく、特にプールサイズのチューニングについての唯一の本当の答えは、負荷とDBサーバーのスループットの堅牢な測定をセットアップし、スイートスポットが見つかるまで上下に調整を開始することです。
クレイグリンガー

@CraigRingerいいえ、私はその人ではありません。しかし、バックリンクをありがとう!PostgreSQLサーバーのチューニングを読み、前述のヒントのいくつかに従いました。これで、デフォルトではない設定が含まれました。私たちは今、メイク、より大きな取引とテストに探しているsynchronous_commit = off
lorgartzor

回答:


14

ここでの簡単な答えは、「監視およびパフォーマンスメトリックによって導かれる試行錯誤」です。

漠然とした領域を見つけるのに役立つ一般的な経験則がいくつかありますが、それらは非常に一般的なものです。「CPUの数+独立したディスクの数」という広範なガイドラインがよく引用されますが、それは信じられないほど粗い出発点にすぎません。

本当に必要なのは、アプリケーションの適切なパフォーマンスメトリックを取得することです。統計の記録を開始します。

このための統合ツールの方法はあまりありません。nagios check_postgresスクリプト、Cactiシステムパフォーマンスカウンターロギング、PostgreSQL統計情報コレクターなどのようなものがありますが、すべてをまとめるものはあまりありません。悲しいことに、あなたはそれを自分でやらなければなりません。PostgreSQL側については、PostgreSQLマニュアルの監視を参照してください。EnterpriseDBのPostgres Enterprise Monitorなど、サードパーティのオプションがいくつかあります。

ここで説明したアプリケーションレベルのメトリックについては、共有データ構造またはRedisなどの外部の非永続DBに記録し、記録するか、PostgreSQL DBに書き込む前に集計する必要があります。Pgに直接ログを記録しようとすると、測定値を記録することで生じるオーバーヘッドで測定値がゆがみ、問題が悪化します。

最も単純なオプションは、おそらく、アプリケーションの統計を記録するために使用する各アプリサーバーのシングルトンです。おそらく、常に最小、最大、n、合計、および平均を更新したいでしょう。そうすれば、各統計ポイントを保存する必要はなく、集計のみを保存する必要があります。このシングルトンは、x分ごとに集計統計をPgに書き込むことができます。これは、パフォーマンスへの影響が最小限になるほど十分に低いレートです。

皮切りに:

  • リクエストの待ち時間はどれくらいですか?つまり、クライアントからのリクエストを取得してからクライアントに応答するまで、アプリはどれくらい時間がかかりますか。これを個別の記録としてではなく、一定期間にわたってまとめて記録します。要求タイプごとにグループ化します。たとえば、ページごとに。

  • アプリが実行する各クエリまたはクエリタイプのデータベースアクセス遅延はどのくらいですか?DBに情報を問い合わせる/情報を保存してから、次のタスクに進むまでにどれくらい時間がかかりますか?繰り返しますが、これらの統計をアプリケーションに集約し、集約情報のみをDBに書き込みます。

  • あなたのスループットはどのくらいですか?任意のx分で、アプリが実行する各主要クラスのクエリは、DBによって何回処理されますか?

  • 同じ時間範囲x分の間に、いくつのクライアントリクエストがありましたか?

  • 数秒ごとにサンプリングし、DB内の同じx分のウィンドウで集計します。そこにはいくつのDB接続がありましたか?何人がアイドル状態でしたか?何人がアクティブでしたか?挿入物で?アップデート?選択しますか?削除しますか?その期間に何件のトランザクションがありましたか?統計情報コレクターのドキュメントを参照してください

  • 同じ時間間隔でサンプリングと集計を繰り返しますが、ホストシステムのパフォーマンスメトリックはどのようなものでしたか?1秒あたりの読み取りディスクIOおよび書き込みディスクIOの数 1秒あたりのメガバイトのディスク読み取りおよび書き込み?CPU使用率?負荷平均?RAMの使用?

これで、データの相関、グラフ化などにより、アプリのパフォーマンスについて学習を開始できます。パターンの表示、ボトルネックの検出を開始します。

あなたは、あなたのシステムがボトルネックにあることを学習する可能性がありますINSERTし、UPDATE秒あたりのメガバイトでかなり低いディスクI / Oにもかかわらず、高いトランザクション・レートでね。これは、バッテリーバックアップ式のライトバックキャッシングRAIDコントローラーまたは高品質の電源保護されたSSDを使用して、ディスクフラッシュのパフォーマンスを改善する必要があることを示唆しています。またsynchronous_commit = off、サーバークラッシュ時にいくつかのトランザクションを失っても問題ない場合、および/またはを使用してcommit_delay、同期負荷の一部を取り除くこともできます。

同時接続の数に対して1秒あたりのトランザクションをグラフ化し、アプリケーションが認識しているさまざまなリクエストレートを修正すると、スループットのスイートスポットがどこにあるかをより正確に把握できるようになります。

高速フラッシュストレージ(BBU RAIDまたは高速耐久性のあるSSD)がない場合は、アクティブな書き込み接続のかなり少ない数、おそらく最大2倍のディスク数、おそらくRAIDの配置に応じてより少ない数を超える必要はありません、ディスクのパフォーマンスなど。この場合、試行錯誤する価値はありません。ストレージサブシステムを、高速ディスクフラッシュを備えたものにアップグレードするだけです。

pg_test_fsyncこれが問題になるかどうかを判断するのに役立つツールを参照してください。ほとんどのPostgreSQLパッケージは、このツールをcontribの一部としてインストールするため、コンパイルする必要はありません。1秒あたり数千オペレーション未満の場合、ストレージシステムpg_test_fsync早急にアップグレードする必要があります。SSD搭載のラップトップは5000-7000を取得します。7200rpm SATAディスクの4ディスクRAID 10アレイとライトスルー(非書き込みキャッシュ)で作業している私のワークステーションは、約80 ops /秒でf_datasync、最低20 ops /秒でfsync(); それは何百倍も遅いです。比較:ノートパソコンのSSDとを持つワークステーションライトスルー(非書き込みキャッシュ)RAID 10。このラップトップのSSDは安価であり、電力損失時に書き込みキャッシュをフラッシュすることを必ずしも信頼しているわけではありません。私は適切なバックアップを保持し、関心のあるデータには使用しません。高品質のSSDは、パフォーマンスが向上していなくても同じように機能し、書き込み耐久性があります。

申請の場合、以下を確認することを強くお勧めします。

  • 高速フラッシュを備えた優れたストレージサブシステム。これを十分に強調することはできません。高品質の電源フェールセーフSSDおよび/または電源保護ライトバックキャッシュを備えたRAIDコントローラー。
  • UNLOGGEDデータにテーブルを使用すると、失うことのできる余裕があります。ログに記録されたテーブルに定期的に集約します。たとえば、ログに記録されていないテーブルで進行中のゲームを保持し、通常の永続テーブルにスコアを書き込みます。
  • 使用commit_delay(高速フラッシュストレージではあまり有用ではありません-ヒント)
  • synchronous_commit失う余裕のあるトランザクションをオフにする(高速フラッシュストレージではあまり役に立たない-ヒントヒント)
  • パーティションテーブル、特にデータが "期限切れ"になり、クリーンアップされるテーブル。パーティションテーブルから削除する代わりに、パーティションを削除します。
  • 部分インデックス
  • 作成するインデックスの数を減らします。すべてのインデックスには書き込みコストがあります。
  • より大きなトランザクションへの作業のバッチ処理
  • 読み取り専用ホットスタンバイレプリカを使用して、メインDBから読み取り負荷を取り除く
  • memcachedやredisなどのキャッシュレイヤーを使用して、頻繁に変更されないデータや古くなったデータに使用します。を使用LISTENNOTIFYて、PostgreSQLテーブルでトリガーを使用してキャッシュの無効化を実行できます。

疑問がある場合:http : //www.postgresql.org/support/professional_support/

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.