Pgpool-IIで高可用なシステム構成を考える
PostgreSQLインサイド

エンタープライズで利用するデータベースシステムは、障害に強く、安定稼動ができるよう、高可用な構成にすることが要求されます。また、将来的にデータ量やアクセス量が増加しても、サーバ増設等による性能向上により、システムの応答速度や処理キャパシティを維持できるよう、スケーラビリティの高いシステムが要求されることもあります。
これらの要求に対応するために、PostgreSQLの周辺ツールの1つである、Pgpool-IIを利用した、高可用なシステム構成について解説します。

1. Pgpool-IIとは

Pgpool-IIは、アプリケーションとデータベースの間で稼動するミドルウェアであり、LinuxやSolaris上で動作します。Pgpool-IIは、主に以下の機能を提供しています。今回は、Pgpool-II 4.0.2をベースに説明します。

表1 Pgpool-IIの主な機能

分類 機能名 説明
性能向上のための機能 負荷分散(ロードバランス) 参照クエリを複数のデータベースサーバへ効率的に振り分けることにより、より多くのクエリを処理します。
コネクションプーリング データベースへの接続を保持/再利用することにより、接続時のオーバーヘッドを低減し、再接続時の性能を向上します。
データベースの高可用のための機能 レプリケーション 複数のデータベースサーバに常に同じデータを保存することにより、データベースを冗長化します。(注1
自動フェイルオーバ プライマリー側のデータベースサーバの障害発生時に、自動的にスタンバイ側のデータベースサーバに切り替えることで、業務を継続します。
オンラインリカバリー 業務を止めることなく、データベースサーバの復旧や追加を行います。
Pgpool-IIの高可用のための機能 Watchdog 複数のPgpool-IIを連携させて、相互に死活監視やサーバ情報を共有します。障害発生時には自律的に切り替えを行います。
  • (注1)
    Pgpool-IIには、独自のレプリケーション機能だけでなく、他のレプリケーション機能を利用する方式も選択できます。その中でも、PostgreSQL本体の「ストリーミングレプリケーション機能」を利用する方式が推奨されています。「ストリーミングレプリケーション」は、PostgreSQL(プライマリー)のトランザクションログ(WAL)を、複数のPostgreSQL(スタンバイ)に転送することで、データベースを複製する機能です。詳細は「ストリーミングレプリケーション ~仕組み、構成のポイント~」で説明しています。

図1 ストリーミングレプリケーション機能

1.1 負荷分散とコネクションプーリング

データベースを構成するサーバの台数を増やし、システム全体の処理能力を高める手段として、スケールアウトがあります。PostgreSQLでは、ストリーミングレプリケーション機能を使うことでスケールアウトを実現できます。また、スケールアウトを利用するためには、アプリケーションからのクエリを効率的に各データベースサーバに振り分ける必要があります。PostgreSQL本体にはその機能がありませんので、Pgpool-IIの「負荷分散機能」を使うことによって、参照クエリを効率的に振り分け、負荷を分散することができます。
また、データベースサーバへの接続にはオーバーヘッドがあるため、その操作が繰り返されるとスループットの低下につながります。Pgpool-IIの「コネクションプーリング機能」を使うことにより、保持されたコネクションが再利用できるようになるため、オーバーヘッドを軽減することができます。
これらの処理は、Pgpool-IIの設定ファイルの該当パラメーターを設定することで動作させることができます。

図2 Pgpool-IIの負荷分散とコネクションプーリング

1.2 自動フェイルオーバとオンラインリカバリー

Pgpool-IIの「自動フェイルオーバ機能」と「オンラインリカバリー機能」について説明します。なお、Pgpool-IIでは、「レプリケーション機能」に、PostgreSQL本体の「ストリーミングレプリケーション」を利用することを推奨しているため、以降の説明は、「ストリーミングレプリケーション」の利用を前提とします。
「自動フェイルオーバ機能」は、Pgpool-IIがPostgreSQLのプライマリーサーバで異常を検知すると、以下の処理を自動で実行します。なお、②および③の処理は、あらかじめスクリプトで作成し、Pgpool-IIに設定しておく必要があります。

  1. 障害が発生したプライマリーサーバを切り離し、Pgpool-IIからのクエリ振り分けを止める
  2. スタンバイサーバを新プライマリーサーバに昇格させる
  3. 各PostgreSQLについて、レプリケーションの同期先を変更する

図3 Pgpool-IIの自動フェイルオーバ機能

「オンラインリカバリー機能」は、Pgpool-IIからオンラインリカバリー用のコマンドを実行することで、切り離されていた旧プライマリーサーバをスタンバイとして組み込みます。このコマンドは、以下の処理を行います。なお、これらの処理は、あらかじめスクリプトで作成し、データベースサーバ側に格納しておく必要があります。

  1. 旧プライマリーサーバを、新プライマリーサーバのデータを基に再構築してスタンバイとして組み込む
  2. 各PostgreSQLについて、レプリケーションの同期先を変更する

図4 Pgpool-IIのオンラインリカバリー機能

参考

Pgpool-IIの「オンラインリカバリー機能」は、データベースサーバ側のPostgreSQLに対して、拡張機能としてインストールしておく必要があります。

1.3 Watchdog

システム全体の高可用を実現するためには、Pgpool-II自身を冗長化する必要があります。その冗長化に必要な機能が「Watchdog機能」です。「Watchdog機能」は、複数のPgpool-IIをアクティブ / スタンバイ構成で相互に連携させ、互いに、死活監視と、サーバ情報(ホスト名、ポート番号、Pgpool-IIのステータス、仮想IP情報、起動時間)を共有します。サービスを提供するPgpool-II(アクティブ)に障害が発生した場合は、自律的に、Pgpool-II(スタンバイ)がそれを検知してフェイルオーバします。その際、新しいPgpool-II(アクティブ)は仮想IPインターフェースを立ち上げ、以前のPgpool-II(アクティブ)は、仮想IPインターフェースを停止します。これにより、アプリケーション側からは、サーバが切り替わっても同じIPアドレスでPgpool-IIを使うことができます。また、「Watchdog機能」を使うことで、各Pgpool-IIは連携・協調して、データベースサーバの監視やフェイルオーバ指示を行います。その際、Pgpool-II(アクティブ)が取りまとめ役として動作します。
これらの処理は、Pgpool-IIの設定ファイルの該当パラメーターを設定することで動作させることができます。

図5 Pgpool-IIのWatchdog機能を利用した構成

冗長化構成において「Pgpool-IIのスプリットブレイン」と「データベース(PostgreSQL)のスプリットブレイン」を考慮する必要があります。スプリットブレインとは、アクティブなサーバが複数存在してしまう状態を指します。この状態でデータの更新作業を行うと、データの不整合が起こり、復旧が非常に困難な状態になります。Pgpool-IIでは、これらの問題を回避するために、Pgpool-IIを3台以上、かつ、奇数台のサーバで構成することを推奨しています。
それぞれのスプリットブレインが発生するタイミングの例は以下の通りです。

  • Pgpool-IIのスプリットブレイン
    Pgpool-IIが2台構成のとき、Pgpool-IIを結ぶネットワークのみに異常が発生(フェイルオーバについては抑止されますが、Pgpool-IIの連携・協調が動作しなくなります)
  • データベース(PostgreSQL)のスプリットブレイン
    Pgpool-IIが2台構成のとき、Pgpool-II(アクティブ)とPostgreSQL(プライマリー)の間を結ぶネットワークに異常が発生(2台構成では、後述する、多数決による判定が行われません)

ここで、Pgpool-IIが3台構成のときの「Watchdog機能」が、データベースのスプリットブレインの発生を回避する例を見てみましょう。

① Pgpool-II(アクティブ)は、PostgreSQL(プライマリー)との間のネットワーク断線により、障害を検知する

このとき、Pgpool-II(アクティブ)は、PostgreSQL(プライマリー)が稼動しているかどうか判断できません。

② フェイルオーバするかどうかの処理判断を、他のPgpool-II(スタンバイ)にも投票させる

図6 ネットワーク障害が発生したときのWatchdog機能の動作(障害検知と投票)

③ 「フェイルオーバする」という投票結果が過半数に達していないため、フェイルオーバを行わない

ここで、スプリットブレインが回避されます。また、Pgpool-II(アクティブ)は、PostgreSQL(プライマリー)へのクエリ振り分けを止めます(隔離)。

④ アクティブのPgpool-IIで障害検知が行われた場合、アクティブ/スタンバイの切り替えを行う

この結果、アプリケーション側からの更新クエリが継続して実行できます。

図7 ネットワーク障害が発生したときのWatchdog機能の動作(判断と対処)

2. Pgpool-IIを利用したシステム構成

実際のビジネス利用を想定したシステム構成の検討と、簡単な動作確認を行います。

2.1 システム構成の検討

Pgpool-IIを利用した実際のビジネス利用を想定し、以下の要件を満たしたシステム構成を考えてみます。

  • スプリットブレインを考慮した高可用構成
  • 将来的なスケールアウト
  • 性能を考慮し、負荷分散機能とコネクションプーリング機能を利用

一般的に、ハードウェア、および、ソフトウェアを選定する際には、コストパフォーマンスを考慮し、シンプルで効率的な構成にします。そのために、まず検討すべきことは、Pgpool-IIの配置場所です。以下に配置場所ごとの特徴(影響)を示します。

表2 Pgpool-IIの配置場所による影響比較

配置場所 サーバ負荷影響 ネットワーク影響 サーバコスト(台数)
専用サーバ 他のソフトウェアの影響を受けない アプリケーションとPgpool-II間、および、Pgpool-IIとデータベース間のネットワークの影響を受ける Pgpool-IIを運用するサーバが、別途必要(推奨は3台以上、かつ、奇数台)
データベースサーバ(同居) 同居先データベースの性能影響を受けると共に同居先サーバの冗長化や拡張性を考慮する必要がある Pgpool-IIとデータベース間を一部ローカル接続にできるため、この部分のネットワーク影響が少ない Pgpool-IIの同居先サーバは3台以上を推奨しており、データベースサーバの台数によっては、別途必要
アプリケーションサーバやWebサーバ(同居) 同居先のソフトウェアの性能影響を受けると共に同居先サーバの冗長化や拡張性を考慮する必要がある アプリケーション(Webサーバ)とPgpool-II間をローカル接続にできるため、この部分のネットワーク影響を受けない Pgpool-IIの同居先サーバは3台以上を推奨しており、アプリケーションサーバ(Webサーバ)の台数によっては、別途必要

始めに、Pgpool-IIをデータベースサーバに同居した場合の構成例を見てみましょう。なお、実際のシステム構成を想定し、クライアントからのリクエストが別途ロードバランサーなどで負荷分散され、3台のアプリケーションサーバでアプリケーションが並行処理されることとします。図中の「APL」はアプリケーション、「Pgpool」はPgpool-II、「(A)」はアクティブ、「(P)」はプライマリー、「(S)」はスタンバイを意味しています。Pgpool-II同士はWatchdogで協調動作させます。スケールアウトは、データベースサーバ3にPostgreSQL(S)を追加、さらには、データベースサーバ4台目以降を追加していくことで実現できます。
なお、この構成では、Pgpool-II(アクティブ)が動作するデータベースサーバに負荷が集中するため、それを考慮する必要があります。

図8 Pgpool-IIを利用したシステム構成例(データベースサーバに同居)

次に、Pgpool-IIをアプリケーションサーバに同居した場合の構成例を見てみましょう。Pgpool-IIは、マルチマスタ構成で動作させるため、固定IPを割り当てて利用します。その結果、以下のメリットが得られるようになります。

  • Pgpool-IIの負荷分散ができる
  • すべてのPgpool-IIのアクティブ / スタンバイにおいて、更新や参照クエリを受け付けることができる
  • アプリケーションとPgpool-II間のネットワークオーバーヘッドを減らすことができる

なお、マルチマスタ構成においても、Pgpool-II(アクティブ)が取りまとめ役として動作してデータベースを制御します。また、この構成におけるスケールアウトについては、データベースサーバ3台目以降を増やしていくことで実現できます。

図9 Pgpool-IIを利用したシステム構成例(アプリケーションサーバに同居)

2.2 動作確認

Pgpool-IIをアプリケーションサーバに同居した構成(図9)において、自動フェイルオーバ、および、オンラインリカバリーの実際の動作について見てみましょう。なお、PostgreSQLとPgpool-IIはインストール、設定、起動が済んでいることを前提とします。

  1. アプリケーションサーバ1のPgpool-II(アクティブ)に接続し、データベースサーバの状態を確認します。なお、データベースサーバ1のホスト名はhost0、データベースサーバ2のホスト名はhost1です。また、Pgpool-II(アクティブ)の存在するアプリケーションサーバ1のホスト名はhost5です。
$ psql -h host5 -p 9999 -U postgres
postgres=# SHOW pool_nodes;
 node_id | hostname | port | status | lb_weight |  role   | select_cnt | load_balance_node | replication_delay | last_status_change  
---------+----------+------+--------+-----------+---------+------------+-------------------+-------------------+---------------------
 0       | host0    | 5432 | up     | 0.500000  | primary | 2          | false             | 0                 | 2019-05-27 14:43:54
 1       | host1    | 5432 | up     | 0.500000  | standby | 2          | true              | 0                 | 2019-05-27 14:43:54
(2 rows)
  1. データベースサーバ1(host0)のPostgreSQL(プライマリー)を強制停止します。
$ pg_ctl -m immediate stop
  1. アプリケーションサーバ1から、再度、データベースサーバの状態を確認します。1度目の接続は失敗しますが、リセットが行われてデータベースへの接続が復旧するため、2度目の接続は成功します。データベースのサーバの状態を見ると、host0の「status」が「down」状態になり、また、「role」の状態が入れ替わっていることから、host1に自動的にフェイルオーバし、プライマリーに昇格したことがわかります。
postgres=# SHOW pool_nodes;
server closed the connection unexpectedly
    This probably means the server terminated abnormally
    before or while processing the request.
The connection to the server was lost. Attempting reset: Succeeded.
postgres=# SHOW pool_nodes;
 node_id | hostname | port | status | lb_weight |  role   | select_cnt | load_balance_node | replication_delay | last_status_change  
---------+----------+------+--------+-----------+---------+------------+-------------------+-------------------+---------------------
 0       | host0    | 5432 | down   | 0.500000  | standby | 2          | false             | 0                 | 2019-05-27 14:47:20
 1       | host1    | 5432 | up     | 0.500000  | primary | 2          | true              | 0                 | 2019-05-27 14:47:20
(2 rows)
  1. アプリケーションサーバ1から、データベース1(host0)に対するオンラインリカバリーコマンドを実行します。正常終了したことを確認します。
$ pcp_recovery_node -h host5 -p 9898 -U postgres -n 0
Password: (パスワードを入力)
pcp_recovery_node -- Command Successful
  1. アプリケーションサーバ1から、再度、データベースサーバの状態を確認します。オンラインリカバリー後も、1度目のデータベースへの接続のときにリセットされ、2度目の接続は成功します。host0の「status」が「up」状態になったことから、host0がスタンバイとして復旧したことがわかります。
postgres=# SHOW pool_nodes;
ERROR:  connection terminated due to online recovery
DETAIL:  child connection forced to terminate due to client_idle_limitis:-1
server closed the connection unexpectedly
    This probably means the server terminated abnormally
    before or while processing the request.
The connection to the server was lost. Attempting reset: Succeeded.
postgres=# SHOW pool_nodes;
 node_id | hostname | port | status | lb_weight |  role   | select_cnt | load_balance_node | replication_delay | last_status_change  
---------+----------+------+--------+-----------+---------+------------+-------------------+-------------------+---------------------
 0       | host0    | 5432 | up     | 0.500000  | standby | 2          | true              | 0                 | 2019-05-27 14:50:13
 1       | host1    | 5432 | up     | 0.500000  | primary | 2          | false             | 0                 | 2019-05-27 14:47:20
(2 rows)

3. 留意事項

Pgpool-IIは、エンタープライズ利用に向けた、PostgreSQLの有用な周辺ツールであることが確認できました。そして、実際に適用できるシステム形態としては、同時接続数が多く、スケールアウトで対応するような、中・大規模システムに向いていることも確認できました。
なお、Pgpool-IIを活用する上では、以下の留意点があります。

  • 環境構築における設定項目が多く、また、用意すべきスクリプトは利用者が作成する必要があるため、設計や環境構築には、十分な検討と検証を行う必要があります。
  • 負荷分散については、参照系のクエリが対象になるため、更新系のクエリが多いシステムについては、性能を向上させることができません。なお、データベースサーバ数を増やすほど、参照性能は向上しますが、更新性能は劣化する場合があります。

FUJITSU Software Enterprise Postgres(以降、Enterprise Postgresと略します)では、バージョン 10からPgpool-IIを同梱していますが、Enterprise Postgresにも以下の機能があります。

  • アプリケーションの接続先切り替え機能
    プライマリーサーバ、スタンバイサーバを意識せずに、データベースへの接続を切替えるクライアント側の機能です。
  • データベース多重化機能
    ストリーミングレプリケーション上で動作する運用機能です。データベースプロセス、ディスク、ネットワークなどの障害を検知し、自動切離しやフェイルオーバ機能などを提供します。

Pgpool-IIとEnterprise Postgresが持つ、同様の機能は併用して利用することができませんのでご留意ください。なお、同様の機能を併用しない、Pgpool-IIの「負荷分散機能」や「コネクションプーリング機能」と、Enterprise Postgresの「データベース多重化機能」を組み合わせた利用は可能です。

高可用を実現する上での、環境構築や検証については、難易度が高いことが想定されます。Enterprise Postgresに同梱しているPgpool-IIは、富士通の24時間365日保守サポートにより、PostgreSQL本体およびPgpool-IIを含む周辺ツールのご質問、トラブル対応およびバグ修正にも迅速に対応しますので、ご利用を検討ください。

2020年2月14日更新

本コンテンツに関するお問い合わせ

お電話でのお問い合わせ

Webでのお問い合わせ

当社はセキュリティ保護の観点からSSL技術を使用しております。

ページの先頭へ