PostgreSQLでlibpqまたはJava Database Connectivity (JDBC) を使用して、簡単な設定の後に自動フェールオーバーと読み書き分離を実装できます。
背景情報
PostgreSQL 10以降では、libpqはフェールオーバーをサポートし、JDBCはドライバー層でのフェールオーバーと負荷分散をサポートします。
libpqはPostgreSQLへのC APIです。 libpqは、クライアントプログラムがバックエンドPostgreSQLサーバーにクエリを送信し、これらのクエリの結果を受信できるようにするライブラリ関数のセットです。
JDBCは、クライアントプログラムがデータベースにアクセスする方法を定義するJava APIです。 PostgreSQLでは、JDBCはフェールオーバーと負荷分散をサポートします。
libpqを使用した自動フェールオーバーと読み書き分離の実装
libpq関数を使用して、複数のデータベースに接続できます。 1つのデータベースに障害が発生すると、サービスは他の利用可能なデータベースに自動的に切り替えられます。
コマンド
postgresql://[user[:password]@][netloc][:port][,...][/dbname][?param1=value1&...]
例:
次の例では、クライアントがプライマリApsaraDB RDS for PostgreSQLインスタンスとその2つの読み取り専用RDSインスタンスに接続されています。 これらのRDSインスタンスの少なくとも1つが使用可能な場合、読み取り要求は失敗しません。
postgres:// pgm-bpxxx1.pg.rds.aliyuncs.com:3433、pgm-bpxxx2.pg.rds.aliyuncs.com:3433、pgm-bpxxx3.pg.rds.aliyuncs.com:3433/postgres?target_session_attrs=any
target_session_attrs: 接続されているRDSインスタンスのステータスを指定します。 有効な値:
any: クライアントは、データベースシステム内のRDSインスタンスにランダムに接続します。 RDSインスタンスに障害があるために接続が中断された場合、クライアントはデータベースシステム内の他のRDSインスタンスに接続してフェイルオーバーを実装します。 デフォルト値です。
読み書き: クライアントは、データベースシステムで読み書き操作をサポートするRDSインスタンスにのみ接続します。 クライアントは、データベースシステムのRDSインスタンスに順番に接続します。 RDSインスタンスが読み書き操作をサポートしていない場合、クライアントは、読み書き操作をサポートしているRDSインスタンスに接続するまで、RDSインスタンスから切断して次のRDSインスタンスに接続します。
libpqの使用方法とその他のパラメーターの設定方法の詳細については、「接続文字列」をご参照ください。
アプリケーションでpg_is_in_recovery() 関数を呼び出して、接続されたRDSインスタンスがプライマリRDSインスタンスか読み取り専用RDSインスタンスかを判断できます。 これにより、自動フェールオーバーと読み取り /書き込み分割の実装に役立ちます。 例:
Python
$ cat pg_conn.py インポートpsycopg2 conn = psycopg2.connect(database="postgres" 、host="pgm-bpxxx1.pg.rds.aliyuncs.com、pgm-bpxxx2.pg.rds.aliyuncs.com、pgm-bpxxx3.pg.rds.aliyuncs.com" 、user="testxxx" 、password="xxxxxx" 、port="3433" 、target_session_attrs="読み書き") cur = conn.cursor() cur.exeかわいい ("select pg_is_in_recovery(), pg_postmaster_start_time()") row = cur.fetchone() プリント "recovery =",row[0] プリント "time =",row[1] $python pg_conn.py recovery = False time = 2020-07-09 15:33:57.79001 + 08
説明前の例のprint構文は、Python 2にのみ適用されます。 Python 3を使用する場合は、print構文を次の内容に置き換えます。
プリント ("recovery =", row[0]) プリント ("time =", row[1])
PHP
# cat pg_conn.php <?php $conn = pg_connect("hos t=pgm-bpxxx1.pg.rds.aliyuncs.com、pgm-bpxxx2.pg.rds.aliyuncs.com、pgm-bpxxx3.pg.rds.aliyuncs.comポート=3433 dbname=postgres user=testxxxパスワード=xxxxxx target_session_attrs=読み書き") またはdie("接続できませんでした"); $status = pg_connection_status($conn); if ($status === PGSQL_CONNECTION_OK) { 「接続ステータスok\n」を印刷します。} else { 「接続ステータスが悪い \n」を印刷します。} $sql = pg_query($conn, "select pg_is_in_recovery()"); while ($row = pg_fetch_row($sql)) { echo "Recovery-status: $row[0]\n"; } ?> $php -f pg_conn.php 接続ステータスok Recovery-status: f サーバー: xxx.xxx.xx.xx
JDBCを使用した自動フェールオーバーと読み書き分離の実装
複数のRDSインスタンスを指定し、接続URLでコンマ (,) で区切ることができます。 JDBCドライバは、接続が成功するまで、インスタンスへの接続を順番に試みます。 すべての接続試行が失敗すると、エラーメッセージが返されます。
コマンド
jdbc:postgresql:// node1,node2,node3/accounting?targetServerType=preferSlave&loadBalanceHosts=true
例:
jdbc:postgresql:// pgm-bpxxx1.pg.rds.aliyuncs.com:3433、pgm-bpxxx2.pg.rds.aliyuncs.com:3433、pgm-bpxxx3.pg.rds.aliyuncs.com:3433/accounting?targetServerType=preferSlave&loadBalanceHosts=true
次のリストは、返された結果のパラメーターを示しています。
targetServerType: JDBCドライバが接続するRDSインスタンスを指定します。 有効な値:
any: JDBCドライバは任意のRDSインスタンスに接続します。
master: JDBCドライバはプライマリRDSインスタンスにのみ接続します。
slave: JDBCドライバはセカンダリRDSインスタンスにのみ接続します。
preferSlave: JDBCドライバは優先的にセカンダリRDSインスタンスに接続します。 セカンダリRDSインスタンスが利用できない場合、JDBCドライバはプライマリRDSインスタンスに接続します。
説明プライマリRDSインスタンスは書き込み操作をサポートしますが、セカンダリRDSインスタンスは書き込み操作をサポートしません。
loadBalanceHostsは、RDSインスタンスへの接続の順序を指定します。 有効な値:
False: RDSインスタンスは、コマンドで指定された順序で接続されています。 デフォルト値です。
True: RDSインスタンスはランダムに接続されています。
読み書き分離を実装するには、JDBCドライバの設定時にプライマリRDSインスタンスとセカンダリRDSインスタンスを設定する必要があります。 プライマリRDSインスタンスのtargetServerTypeをmasterに設定し、セカンダリRDSインスタンスのtargetServerTypeをpreferSlaveに設定します。 次に、書き込み操作をプライマリRDSインスタンスで実行し、読み取り操作をセカンダリRDSインスタンスで実行するように指定します。 接続されているRDSインスタンスがプライマリまたはセカンダリまたは読み取り専用のRDSインスタンスであるかどうかを判断する場合は、pg_is_in_recovery() 関数を呼び出すことができます。 これにより、自動フェールオーバーと読み取り /書き込み分割の実装に役立ちます。