Tech Sketch Bucket of Technical Chips by TIS Inc.

PostgreSQLクラスタの可用性確保~pgpool-II並列実行型クラスタを作ってみよう~

Pocket

techsketch-banner-OSS+startingblock(700x65).jpg

PostgreSQLはVer9からストリーミング・レプリケーションの機能が実装され、複数台のサーバで分散して処理を行うクラスタシステムを構成することができるようになりました。ただ、実装するにあたっては幾つかのパターンが考えられます。また、PostgreSQLの負荷分散を行うpgpool-IIも単一障害点になってはいけませんので、これ自身も冗長化する必要があります。
今回は、執筆開始時点での正式バージョンであるpgpool-II Ver3.1.3、PostgreSQL Ver9.1.2を使って、以下のようにpgpool-II、 PostgreSQLを並列実行する形でのクラスタシステムを考えてみたいと思います。

pgpoolクラスタ3.PNG


並列実行型クラスタ構成のメリット

通常、クラスタシステムを構築する場合、大きく分けて、アクティブ/スタンバイ型、アクティブ/アクティブ型の2通りの構成があります。当然ながら、pgpool-IIをクラスタ化するには、どちらの方法でも可能です。(PostgreSQLについては、せっかくストリーミングレプリケーションの機能がありますので、この機能を利用してアクティブ/アクティブ型にしてしまいます。)前者はいわゆるHAクラスタと呼ばれるもので、pgpool-IIの場合には、同じくOSSのクラスタツールであるPacemaker上でpgpool-HAを利用して構築する方法があります。一方、今回構築する並列実行型は、pgpool-IIもアクティブ/アクティブ型にしてしまおうという試みです。この構成にするメリットは以下の点が挙げられます。
・サーバ台数を増やすことで(pgpool-IIの)処理性能を向上させることができる(スケールアウト)
 (HAクラスタの場合は、スケールアップでの性能向上のみ)
・1台のサーバがダウンしても、他のpgpool-IIは稼動しているため、全ての処理が停止することはない
 (HAクラスタの場合は、障害発生からスタンバイ機への切替が完了するまで処理が停止する)

ただし、この構成で構築するには注意すべき点もあります。これからその内容を紹介します。

今回構築するシステム構成

今回は、pgpool-IIサーバ3台、PostgreSQLサーバ3台でのクラスタ構成を構築します。また、PostgreSQLについては、3台の役割をそれぞれマスタ、同期スレーブ、非同期スレーブとして構築します。
pgpoolクラスタ4.PNG

とりあえずの構築自体は、各ツールのマニュアルに従ってやれば難しくはありません。

pgpool-IIによるPostgreSQLのフェイルオーバーの動き

PostgreSQLがダウンした場合、それを検知してフェイルオーバを行うのはpgpool-IIの役割になります。実際には設定ファイル(pgpool.conf)のfailover_command、follow_master_commandに設定したシェルスクリプトにて、対応する処理内容を記述します。シェルスクリプトは標準では添付されていませんので、自身で作成する必要があります。

■PostgreSQL(マスタ)がダウンした際のpgpool-IIのフェイルオーバー動作
pgpoolフェイルオーバ.PNG

pgpool-II並列実行型クラスタの問題点

今回の構成では、3台のサーバの上でpgpool-IIが稼動しています。そして、それらのpgpool-IIの間では一切の連携がありませんので、PostgreSQLの障害検知、及び、フェイルオーバ動作は各pgpool-IIが個別に行います。すると、タイミングにより、以下のような問題が発生します。

■follow_master_commandによる、PostgreSQLスレーブへの複数回の再起動コマンド発行
pgpoolフェイルオーバ2.PNG

①は通常の再起動なので正常に実行できますが、②はタイミングによっては再起動コマンドがエラーになる場合があります。また、③については、pgpool-II #1、#2からしてみれば、自身の処理が終了してからの再起動になりますので、「別の障害が発生した」と認識され、該当のPostgreSQLをクラスタから除外してアクセスを振り分けなくなってしまいます。

今回の構成における対策

上記の問題を解決するため、今回は以下のような対策を採りました。

■follow_master_commandのシェルスクリプトでのチェック処理追加
(1) ロックファイルによる二重実行の防止

上記の②のようにPostgreSQL再起動中に、二重に再起動コマンドを実行することを防止するため、ロックファイルを作成するようにしました。

(2) レプリケーション元(マスタ)設定のチェック

上記の③のように、すでに新マスタからのレプリケーションが行われている状態のときに、再度プロセス再起動が行われることを防止するため、マスタ設定の相違チェックを行う処理を追加しました。
pgpoolフェイルオーバ3.PNG

【PostgreSQLスレーブサーバ用スクリプトサンプル】
pgpool-IIとPostgreSQLが別サーバで稼動する想定で、スクリプトを2つに分けています。

follow_master.sh.txt pgpool-IIから呼び出されるスクリプト。ここからPostgreSQLサーバ上のfollow.shを起動する。
follow.sh.txt PostgreSQLの再起動に関する処理を行うスクリプト。

まとめ

今回は、使用したpgpool-IIのバージョンが3.1.3ということもあり、スクリプト内で対処することで並列実行型クラスタを作ってみました。メリットの所でもお話したように、アクティブ/スタンバイ型のHAクラスタと違い、並列実行型にするとスケールアウトで台数を増やしていくことで処理性能を簡単に増強できることが期待できます。ここで挙げたような問題点もスクリプトでの工夫で克服でき、実用に耐えるレベルになっていると考えていますので、ぜひ並列実行型クラスタにチャレンジしていただければと思います。
また、リリースされたばかりの最新の3.2では、PostgreSQLマスタの状態を、並列実行しているpgpool-II間で情報共有するという機能が盛り込まれているようです。メジャーバージョンアップの最初のバージョンは、実務で使うにはちょっと抵抗がある方も多いと思いますが、落ち着いたらこの機能も検証してみたいと思います。

エンジニア採用中!私たちと一緒に働いてみませんか?