データベースの世界には、高可用性、フェイルオーバー、接続プールなどの多くの一般的な概念があります。それらはすべて、あらゆるシステムに実装するのに便利なものであり、場合によっては必須です。
接続プールは、接続のプールを作成して再利用する方法であり、データベースへの新しい接続を常に開かないようにします。これにより、アプリケーションのパフォーマンスが大幅に向上します。 PgBouncerはPostgreSQL用に設計された人気のある接続プールですが、マルチホスト構成、フェイルオーバー、または検出がないため、PostgreSQLの高可用性を単独で実現するには十分ではありません。
ロードバランサーの使用は、データベーストポロジで高可用性を実現する方法です。トラフィックを正常なデータベースノードにリダイレクトしたり、トラフィックを複数のサーバーに分散してパフォーマンスを向上させたり、アプリケーションで単一のエンドポイントを構成して構成とフェイルオーバーのプロセスを容易にしたりする場合に便利です。このため、HAProxyは、TCPおよびHTTPベースのアプリケーションの高可用性、負荷分散、およびプロキシを実装するために使用できるオープンソースプロキシであるため、接続プールを補完するための優れたオプションです。
このブログでは、ロードバランサーと接続プール(HAProxy + PgBouncer)の両方の概念を使用して、PostgreSQLデータベースの高可用性環境を展開します。
PgBouncerのしくみ
PgBouncerはPostgreSQLサーバーとして機能するため、PgBouncer情報(IPアドレス/ホスト名とポート)を使用してデータベースにアクセスするだけで、PgBouncerはPostgreSQLサーバーへの接続を作成します。存在する場合は再利用します。
PgBouncerは接続を受信すると、構成ファイルで指定された方法に応じて認証を実行します。 PgBouncerは、PostgreSQLサーバーがサポートするすべての認証メカニズムをサポートします。この後、PgBouncerは、同じユーザー名とデータベースの組み合わせで、キャッシュされた接続をチェックします。キャッシュされた接続が見つかった場合は、クライアントに接続を返します。見つからなかった場合は、新しい接続を作成します。 PgBouncerの構成とアクティブな接続の数によっては、新しい接続が作成されるまで、または中止されるまでキューに入れられる可能性があります。
PgBouncerの動作は、構成されているプーリングモードによって異なります。
- セッションプーリング (デフォルト):クライアントが接続すると、クライアントが接続を維持している間、サーバー接続が割り当てられます。クライアントが切断すると、サーバー接続はプールに戻されます。
- トランザクションプーリング :サーバー接続は、トランザクション中にのみクライアントに割り当てられます。 PgBouncerがトランザクションの終了に気付くと、サーバー接続はプールに戻されます。
- ステートメントプーリング :サーバー接続は、クエリが完了した直後にプールに戻されます。このモードでは、マルチステートメントトランザクションが機能しなくなるため、許可されません。
複数のサーバー間でクエリのバランスをとるには、PgBouncer側で、server_lifetimeを小さくし、server_round_robinをオンにすることをお勧めします。デフォルトでは、アイドル状態の接続はLIFOアルゴリズムによって再利用されますが、ロードバランサーを使用するとうまく機能しない場合があります。
PgBouncerのインストール方法
PostgreSQLクラスターとHAProxyがデプロイされており、稼働していることを前提としています。それ以外の場合は、このブログ投稿に従ってPostgreSQLを高可用性に簡単にデプロイできます。
PgBouncerは、各データベースノードまたは外部マシンにインストールできます。いずれの場合も、次のようになります。
PgBouncerソフトウェアを入手するには、PgBouncerダウンロードセクションにアクセスするか、またはRPMまたはDEBリポジトリを使用します。この例では、CentOS 8を使用し、公式のPostgreSQLリポジトリからインストールします。
まず、PostgreSQLサイトから対応するリポジトリをダウンロードしてインストールします(まだインストールしていない場合):
$ wget https://download.postgresql.org/pub/repos/yum/reporpms/EL-8-x86_64/pgdg-redhat-repo-latest.noarch.rpm
$ rpm -Uvh pgdg-redhat-repo-latest.noarch.rpm
次に、PgBouncerパッケージをインストールします。
$ yum install pgbouncer
$ pgbouncer --version
PgBouncer 1.14.0
libevent 2.1.8-stable
adns: c-ares 1.13.0
tls: OpenSSL 1.1.1c FIPS 28 May 2019
完了すると、/ etc / pgbouncer/pgbouncer.iniに新しい構成ファイルが作成されます。
[databases]
[users]
[pgbouncer]
logfile = /var/log/pgbouncer/pgbouncer.log
pidfile = /var/run/pgbouncer/pgbouncer.pid
listen_addr = 127.0.0.1
listen_port = 6432
auth_type = trust
auth_file = /etc/pgbouncer/userlist.txt
admin_users = postgres
stats_users = stats, postgres
- データベースセクション[データベース]: これには、キーがデータベース名として使用され、値がキー=値のペアのlibpq接続文字列スタイルリストとして使用されるキー=値のペアが含まれます。
- ユーザーセクション[ユーザー]: これには、キーがユーザー名として使用され、値がこのユーザーに固有の構成設定のキー=値のペアのlibpq接続文字列スタイルリストとして使用されるキー=値のペアが含まれます。
- ログファイル :ログファイルを指定します。ログファイルは開いたままなので、ローテーション後にkill-HUPまたはコンソールRELOAD;行う必要があります。
- pidfile :PIDファイルを指定します。 pidfileが設定されていないと、デーモンは許可されません。
- listen_addr :TCP接続をリッスンするアドレスのリストを指定します。 「すべてのアドレスを聞く」という意味の*を使用することもできます。設定されていない場合、Unixソケット接続のみが受け入れられます。
- listen_port: リッスンするポート。 TCPソケットとUnixソケットの両方に適用されます。デフォルトのポートは6432です。
- auth_type: ユーザーを認証する方法。
- auth_file :ユーザー名とパスワードをロードするファイルの名前。
- admin_users :コンソールですべてのコマンドに接続して実行できるデータベースユーザーのコンマ区切りのリスト。
- stats_users :コンソールで接続して読み取り専用クエリを実行できるデータベースユーザーのコンマ区切りのリスト。
これはデフォルトの構成ファイルのサンプルにすぎません。元のファイルには359行ありますが、残りの行はデフォルトでコメント化されています。使用可能なすべてのパラメータを取得するには、公式ドキュメントを確認してください。
PgBouncerの使用方法
それでは、それを機能させるための基本的な構成を見てみましょう。
pgbouncer.ini構成ファイル:
$ cat /etc/pgbouncer/pgbouncer.ini
[databases]
world = host=127.0.0.1 port=5432 dbname=world
[pgbouncer]
logfile = /var/log/pgbouncer/pgbouncer.log
pidfile = /var/run/pgbouncer/pgbouncer.pid
listen_addr = *
listen_port = 6432
auth_type = md5
auth_file = /etc/pgbouncer/userlist.txt
admin_users = admindb
そして認証ファイル:
$ cat /etc/pgbouncer/userlist.txt
"admindb" "root123"
したがって、この場合、同じデータベースノードにPgBouncerをインストールし、すべてのIPアドレスをリッスンし、「world」と呼ばれるPostgreSQLデータベースに接続します。また、userlist.txtファイルで許可されているユーザーを、必要に応じて暗号化できるプレーンテキストのパスワードで管理しています。
PgBouncerサービスを開始するには、次のコマンドを実行する必要があります。
$ pgbouncer -d /etc/pgbouncer/pgbouncer.ini
ここで、-dは「デーモン」を意味するため、バックグラウンドで実行されます。
$ netstat -pltn
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:6432 0.0.0.0:* LISTEN 4274/pgbouncer
tcp6 0 0 :::6432 :::* LISTEN 4274/pgbouncer
ご覧のとおり、PgBouncerは起動しており、ポート6432で接続を待機しています。PostgreSQLデータベースにアクセスするには、ローカル情報(ポート、ホスト、ユーザー名、データベース名)を使用して次のコマンドを実行します。 :
$ psql -p 6432 -h 127.0.0.1 -U admindb world
Password for user admindb:
psql (12.4)
Type "help" for help.
world=#
データベース名(world)は、PgBouncer構成ファイルで構成されたデータベースであることに注意してください。
[databases]
world = host=127.0.0.1 port=5432 dbname=world
PgBouncerの監視と管理
PostgreSQLデータベースにアクセスする代わりに、PgBouncerに直接接続してデータベースを管理または監視できます。これには、前に使用したのと同じコマンドを使用しますが、データベースを「pgbouncer」に変更します。
$ psql -p 6432 -h 127.0.0.1 -U admindb pgbouncer
Password for user admindb:
psql (12.4, server 1.14.0/bouncer)
Type "help" for help.
pgbouncer=# SHOW HELP;
NOTICE: Console usage
DETAIL:
SHOW HELP|CONFIG|DATABASES|POOLS|CLIENTS|SERVERS|USERS|VERSION
SHOW FDS|SOCKETS|ACTIVE_SOCKETS|LISTS|MEM
SHOW DNS_HOSTS|DNS_ZONES
SHOW STATS|STATS_TOTALS|STATS_AVERAGES|TOTALS
SET key = arg
RELOAD
PAUSE [<db>]
RESUME [<db>]
DISABLE <db>
ENABLE <db>
RECONNECT [<db>]
KILL <db>
SUSPEND
SHUTDOWN
SHOW
これで、さまざまなPgBouncerコマンドを実行して監視できるようになりました:
STATS_TOTALSを表示:
pgbouncer=# SHOW STATS_TOTALS;
database | xact_count | query_count | bytes_received | bytes_sent | xact_time | query_time | wait_time
-----------+------------+-------------+----------------+------------+-----------+------------+-----------
pgbouncer | 1 | 1 | 0 | 0 | 0 | 0 | 0
world | 2 | 2 | 59 | 234205 | 8351 | 8351 | 4828
(2 rows)
サーバーを表示する:
pgbouncer=# SHOW SERVERS;
type | user | database | state | addr | port | local_addr | local_port | connect_time | request_time
| wait | wait_us | close_needed | ptr | link | remote_pid | tls
------+---------+----------+--------+-----------+------+------------+------------+-------------------------+-------------------------
+------+---------+--------------+----------------+----------------+------------+-----
S | admindb | world | active | 127.0.0.1 | 5432 | 127.0.0.1 | 45052 | 2020-09-09 18:31:57 UTC | 2020-09-09 18:32:04 UTC
| 0 | 0 | 0 | 0x55b04a51b3d0 | 0x55b04a514810 | 5738 |
(1 row)
クライアントを表示:
pgbouncer=# SHOW CLIENTS;
type | user | database | state | addr | port | local_addr | local_port | connect_time | request_time
| wait | wait_us | close_needed | ptr | link | remote_pid | tls
------+---------+-----------+--------+-----------+-------+------------+------------+-------------------------+-----------------------
--+------+---------+--------------+----------------+----------------+------------+-----
C | admindb | pgbouncer | active | 127.0.0.1 | 46950 | 127.0.0.1 | 6432 | 2020-09-09 18:29:46 UTC | 2020-09-09 18:55:11 UT
C | 1441 | 855140 | 0 | 0x55b04a5145e0 | | 0 |
C | admindb | world | active | 127.0.0.1 | 47710 | 127.0.0.1 | 6432 | 2020-09-09 18:31:41 UTC | 2020-09-09 18:32:04 UT
C | 0 | 0 | 0 | 0x55b04a514810 | 0x55b04a51b3d0 | 0 |
(2 rows)
ショープール:
pgbouncer=# SHOW POOLS;
database | user | cl_active | cl_waiting | sv_active | sv_idle | sv_used | sv_tested | sv_login | maxwait | maxwait_us | pool_
mode
-----------+-----------+-----------+------------+-----------+---------+---------+-----------+----------+---------+------------+------
-----
pgbouncer | pgbouncer | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | state
ment
world | admindb | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | sessi
on
(2 rows)
リロード:
pgbouncer=# RELOAD;
RELOAD
一時停止:
pgbouncer=# PAUSE world;
PAUSE
履歴書:
pgbouncer=# RESUME world;
RESUME
PgBouncer + HAProxy + PostgreSQLを組み合わせて使用することは、PostgreSQLクラスターの高可用性を実現し、同時にデータベースのパフォーマンスを向上させるための優れた方法です。
ご覧のとおり、数回クリックするだけでClusterControlを使用してデプロイできるPostgreSQL環境が整っている場合は、PgBouncerを簡単に追加して、システムに接続プールを利用できます。