8.1. 基本設定の例

8.1.1. さあ始めましょう

ここでは、レプリケーションを行うための準備として、Pgpool-II のインストールや設定、データベースノードの準備について説明します。

8.1.1.1. Pgpool-IIのインストール

Pgpool-IIのインストールはとても簡単です。 ソースのtar ballを展開したディレクトリで以下のようにコマンドを実行します。

     $ ./configure
     $ make
     $ make install
    

configureスクリプトはシステム情報を収集しコンパイル処理に利用します。 configureスクリプトにコマンドライン引数を指定することにより、インストール先ディレクトリなど、デフォルトの動作を変更することができます。 デフォルトではPgpool-II/usr/localディレクトリ以下にインストールされます。

makeコマンドはソースコードをコンパイルし、make installコマンドで実行可能ファイルがインストールされます。 インストール先ディレクトリに書き込み権限を持っている必要があります。 ここでは、Pgpool-II/usr/localにインストールすることにします。

注意: Pgpool-IIPostgreSQL 7.4 以降のlibpqライブラリ(3.0 プロトコル)を必要とします。

configureスクリプトが以下のエラーメッセージを表示した場合、libpqライブラリがインストールされていないか、バージョンが3.0でない可能性があります。

     configure: error: libpq is not installed or libpq is old
    

プロトコルのバージョンが3.0のlibpqライブラリがインストールされているにも係わらず上記のエラーメッセージが表示される場合、configureスクリプトにlibpqライブラリが認識されていない可能性があります。 configureスクリプトは標準では/usr/local/pgsqlディレクトリ以下からlibpqライブラリを検索します。 PostgreSQLのインストール先が/usr/local/pgsqlディレクトリ以下でなければ、configureスクリプトを実行する際にコマンドライン引数として--with-pgsql--with-pgsql-includedir--with-pgsql-libdirオプションを指定してください。

8.1.1.2. 設定ファイルの作成

Pgpool-IIの設定パラメータはpgpool.confファイルに保存されています。 ファイルは、1 行ごとにパラメータ名 = 値という書式です。 Pgpool-II をインストールすると、pgpool.conf.sampleファイルが作成されます。 それをpgpool.confというファイル名にコピーしてから編集するといいでしょう。

     $ cp /usr/local/etc/pgpool.conf.sample /usr/local/etc/pgpool.conf
    

Pgpool-II はデフォルトではローカルホストからのポート番号9999への接続のみを受け付けます。 Pgpool-II と異なるホストからの接続を受け付けたい場合は、listen_addresses'*'に設定します。

      listen_addresses = 'localhost'
      port = 9999
     

ここではデフォルトのパラメータを使うことにします。

8.1.1.3. PCPコマンドの設定

Pgpool-IIには、データベースノードの情報取得やPgpool-II停止などをネットワーク越しに行える管理目的のインターフェイスがあります。 PCPコマンドを使用するにはユーザ認証が必要になります。 この認証はPostgreSQLユーザの認証とは異なります。 ユーザ名とパスワードがpcp.confファイルに定義されている必要があります。 このファイルでは、1行ごとにユーザ名とパスワードがペアとしてリストされており、これらがコロン(:)で区切られています。 パスワードはMD5ハッシュ形式で暗号化されている必要があります。

     postgres:e8a48653851e28c69d0506508fb27fc5
    

Pgpool-II をインストールするとサンプルとしてpcp.conf.sampleが自動的に生成されます。 それをpcp.confというファイル名にコピーしてから編集するといいでしょう。

     $ cp /usr/local/etc/pcp.conf.sample /usr/local/etc/pcp.conf
    

パスワードをMD5ハッシュ形式に変換する際には、Pgpool-IIとともにインストールされるpg_md5コマンドを使用します。 pg_md5コマンドは、コマンドライン引数として文字列を指定すると、それをMD5ハッシュ化したものを表示します。 例えば、以下のようにコマンドライン引数として"postgres"を指定して実行すると、それをMD5ハッシュ化したテキストが標準出力に表示されます。

     $ /usr/local/bin/pg_md5 postgres
     e8a48653851e28c69d0506508fb27fc5
    

PCPコマンドはネットワークを通して実行されるので、ポート番号をpgpool.confファイルのpcp_portパラメータに設定します。 ここでは、pcp_portのデフォルトである9898を使用することにします。

       pcp_port = 9898
      

8.1.1.4. データベースノードの準備

次に、Pgpool-IIのためのPostgreSQLサーバを設定する必要があります。 これらのサーバは、Pgpool-II と同じホストで起動しても、異なるホストであっても構いません。 同じホストにサーバを配置するのならば、各サーバにそれぞれ異なるポート番号を割り合てなければなりません。 異なるマシンで起動する場合は Pgpool-IIからのネットワーク接続を受け入れられるよう適切に設定されている必要があります。 この設定例では、事前に3つのPostgreSQLサーバを作成しておき、それぞれのPostgreSQLサーバの情報を次のパラメータに指定します。

     backend_hostname0 = 'localhost'
     backend_port0 = 5432
     backend_weight0 = 1
     backend_hostname1 = 'localhost'
     backend_port1 = 5433
     backend_weight1 = 1
     backend_hostname2 = 'localhost'
     backend_port2 = 5434
     backend_weight2 = 1
    

backend_hostnamebackend_portbackend_weightには、ノードのホスト名、ポート番号、負荷分散の割合を設定します。 各パラメータ名の後ろには、ノードIDが0から始まる整数(すなわち、0, 1, 2, ...)で指定されていなければなりません。

注意: すべてのノードでbackend_weightパラメータが1に設定されているのは、SELECTクエリが3台のサーバで等しく分散されることを意味しています。

8.1.1.5. Pgpool-IIの起動と停止

Pgpool-II を起動するにはターミナルで以下のコマンドを実行します。

     $ pgpool
    

しかしこれでは、Pgpool-IIが制御端末を切り離すため、ログが出力されません。 Pgpool-IIにログメッセージを表示させたい場合、pgpoolコマンドに-nオプションを指定すると、Pgpool-IIは非デーモンプロセスとして起動し、制御端末は切り離されません。

     $ pgpool -n &
    

コマンドを実行した端末にログメッセージが表示されるので、以下のようなオプションを使うことをお勧めします。

     $ pgpool -n -d > /tmp/pgpool.log 2>&1 &
    

-d オプションはデバッグメッセージの出力を有効にします。 上記の例はファイルにリダイレクトさせているため、ログメッセージが/tmp/pgpool.logに追加され続けます。 ログをローテートさせたい場合は、ローテート機能を持った外部コマンドにログを渡してください。 たとえば、Apache2のrotatelogsが使用できます。

     $ pgpool -n 2>&1 | /usr/local/apache2/bin/rotatelogs \
     -l -f /var/log/pgpool/pgpool.log.%A 86400 &
    

これにより毎日夜中の0時にログがローテートされ、pgpool.log.Thursdayのような名前のログファイルが毎日作成されます。 ただし、すでに同じ名前のファイルがある場合にはrotatelogsはログをそのファイルに追加してしまいます。 cronを使うことで、古いログファイルをローテーションの前に削除することができます。

     55 23 * * * /usr/bin/find /var/log/pgpool -type f -mtime +5 -exec /bin/rm -f '{}' \;
    

注意:Linuxディストリビューションによっては、rotatelogsは/usr/sbin/rotatelogs2として存在しているかもしれません。 -fオプションはrotatelogsが起動された直後に直ちにログファイルを作るオプションで、apache2 2.2.9以降でのみ有効です。 cronologを使うこともできます。

     $ pgpool -n 2>&1 | /usr/sbin/cronolog \
     --hardlink=/var/log/pgsql/pgpool.log \
     '/var/log/pgsql/%Y-%m-%d-pgpool.log' &
    

Pgpool-II を停止するには以下のコマンドを実行します。

     $ pgpool stop
    

Pgpool-II を停止する際にクライアントが接続している場合、Pgpool-IIはその接続が切断されるまで待ってから停止します。 Pgpool-IIを強制的にシャットダウンしたい場合は、以下のコマンドを実行します。

     $ pgpool -m fast stop
    

8.1.2. 初めてのレプリケーション

ネィティブレプリケーションモード(ネイティブレプリケーションモードを参照)では複数のデータベースノードに同じデータを複製して格納します。 ここでは、項8.1.1で準備した 3 台のデータベースノードを使用し、一歩一歩データベースクラスタシステムを作っていきましょう。 複製させるサンプルのデータはpgbenchベンチマークプログラムで生成することにします。

8.1.2.1. レプリケーションの設定

データベースノードのレプリケーションを有効にするには、pgpool.confファイルのネイティブレプリケーションモードをonに設定します。

      replication_mode = true
     

ネイティブレプリケーションモードをonに設定することにより、Pgpool-IIは受信したクエリを全てのデータベースノードに送信します。 対して実行され、同じデータが複製されて格納されるようになります。 さらに、load_balance_modeをonに設定することにより、Pgpool-IIはSELECTクエリをデータベースノード間に振り分けます。

	load_balance_mode = true
       

ここでは、ネイティブレプリケーションモードload_balance_modeの両方を有効にします。

8.1.2.2. レプリケーションの確認

上記のpgpool.confの変更をPgpool-IIに反映させるにはPgpool-IIを再起動する必要があります。 「Pgpool-II の起動と停止」項8.1.1.5を参照してください。 pgpool.confの設定と再起動がすんだら、実際にレプリケーションを試してうまく行くことを確認しましょう。 まず、複製するデータベースを作成する必要があります。 これを"bench_replication"と名づけましょう。 このデータベースが全てのノードで作成される必要があります。 createdbコマンドをPgpool-II経由で実行すると、すべてのノードでデータベースが作成されます。

      $ createdb -p 9999 bench_replication
     

そしてpgbench-iオプションを指定して実行します。 -iオプションにより、データベースは事前に定義されたテーブルとデータで初期化されます。

      $ pgbench -i -p 9999 bench_replication
     

pgbench -iによって作成されるテーブルとデータを以下の表にまとめます。 すべてのノードにおいてこれらのテーブルおよびデータが作成されていれば、正常にレプリケーションが動作していることになります。

表 8-1. data summary

テーブル名行数
pgbench_branches1
pgbench_tellers10
pgbench_accounts100000
pgbench_history0

これをチェックするため、簡単なシェルスクリプトを実行してみましょう。 以下のスクリプトはすべてのノード (ポート番号 5432、5433、5434) のデータベースにおけるpgbench_branches、pgbench_tellers、pgbench_accounts、pgbench_historyの行数が表示されます。

     $ for port in 5432 5433 5434; do
     >     echo $port
     >     for table_name in pgbench_branches pgbench_tellers pgbench_accounts pgbench_history; do
     >         echo $table_name
     >         psql -c "SELECT count(*) FROM $table_name" -p $port bench_replication
     >     done
     > done