DBMSの可用性とPostgreSQLのレプリケーション
勤怠管理やERPなど会社内の業務に欠かせないシステムはもちろんのこと、SNSやECサイトなど個人で利用するシステムでも、何かしらのDBMSを利用をするのが一般的です。
もしDBMSで障害が発生した場合、データの参照・更新が滞り、システム全体として役割を果たすことができなくなります。そのためユーザが利用したいときにシステムを利用可能にするためにはDBMSが継続的に稼働していることがとても重要です。
世の中にはDBMSは多数存在し、またDBMSの可用性を上げる機能やツールなどもさまざまに存在します。OSSの代表的なDBMSの一つであるPostgreSQLには可用性向上機能の一つであるレプリケーションが用意されています。
今回は最新バージョンであるPostgreSQL 9.2のレプリケーションについて、機能の紹介、利用時の注意点、設定による性能差について述べます。
PostgreSQL 9.2のレプリケーションと機能紹介
システムの可用性を向上させる効果的な方法の一つに、同じシステムを2台用意して、通常時には片側(マスター)で処理し、マスターの故障時には待機側(スレーブ)で処理を行うマスタースレーブ構成があります。マスターとスレーブの切り替えを素早く行うことがマスタースレーブ構成の可用性向上の鍵です。
データの更新が逐次行われるDBMSでのマスタースレーブ構成では、マスター故障時に素早くスレーブへ切り替えるために、スレーブへの更新内容をどのように伝搬するかが重要です。PostgreSQL 9.0以降ではレプリケーションを用いることで更新内容をリアルタイムに伝搬して、素早くマスターとスレーブを切り替えることが可能になりました。
PostgreSQLのレプリケーションでは、スレーブがマスターを監視し、マスターに更新があった場合、スレーブはマスターから更新情報を取り出します。このマスタースレーブ間でやり取りされるデータの更新情報の実態はWAL(Write Ahead Logging、ログ先行書き込み)です。WALはテーブルに書き込みを行う前に更新情報を記録しているログで、チェックポイント間でDBMSがクラッシュしたときに、クラッシュ直前までリカバリを行うために利用されます。
PostgreSQL 9.2のレプリケーションでは、WALの同期タイミングに対して以下の4つの設定ができます(図1)[1]。
- 同期:マスターと1台のスレーブのディスクへのWALを書き込み後にユーザにレスポンスする(9.1から提供)
- メモリ同期:マスタのディスクと1台のスレーブのメモリへのWALを書き込み後にユーザにレスポンスする(9.2の新機能)
- スレーブ非同期:マスターのディスクへのWALを書き込み後にユーザにレスポンスする(スレーブへの書き込みは確認しない)(9.0から提供)
- 完全非同期:マスター・スレーブともにWAL書き込みを待たずにユーザにレスポンスする(WALはマスターのメモリ上のみ)(9.0から提供)
PostgreSQLのレプリケーションではユーザからのアクセスに対してマスターが更新・参照を、スレーブが参照をそれぞれ担当することができます。つまりマスターへの参照処理負荷をスレーブサーバーに分散できます。今回は可用性向上機能としてレプリケーションを利用するため、負荷分散する方法についての説明は割愛します。
レプリケーションの構成方法
それではPostgreSQLへのレプリケーションの設定方法を紹介します。
まずはマスターです。
以下のSQLでレプリケーション用のユーザを作成します。管理ユーザでもレプリケーションできますが、権限が多すぎるので、できる限りレプリケーション用ユーザを作成しましょう。
CREATE USER repl_user REPLICATION PASSWORD 'xxx';
PostgreSQLの設定ファイルであるpostgres.confに以下のパラメータを記入します。
wal_level = hot_standby #WALの出力内容をレプリケーションに対応 synchronous_commit = on #同期方式の設定 max_wal_senders = 3 #スレーブの数 + 1 synchronous_standby_names = 'slave_hostname' #同期/メモリ同期レプリケーションで同期スレーブとして動作可能なサーバ #これを設定しないとスレーブ非同期レプリケーションで動作する #スレーブのrecovery.confに設定するprimary_conninfoのapplication_name=と同一にする
synchronous_commitパラメータでレプリケーションの同期方式を設定します。
- 同期:on
- メモリ同期:remote_write
- スレーブ非同期:local
- 完全非同期:off
管理ユーザ以外をレプリケーションに使う場合、マスターのpg_hba.confに以下を設定します。
host replication repl_user 0.0.0.0/0 password
次はスレーブです。postgres.confに以下のパラメータを設定します。
hot_standby = on
また、recovery.confに以下の設定をします。
standby_mode = 'on' primary_conninfo = 'host=master_hostname port=5432 user=repl_user password=xxx application_name=slave_hostname' #マスターへの接続情報 #application_nameは同期/メモリ同期の場合にのみ必要 #マスターのpostgres.confに設定したsynchronous_standby_namesと同一にする
以上で構成完了です。
マスターにすでにデータが存在する場合、スレーブを起動する前にpg_basebackupなどを利用してマスターのデータをスレーブに反映しておく必要があります。
また、マスターのWALにスレーブが遅れすぎた場合、スレーブはWALアーカイブを利用してマスターに追いつくことが可能です。詳しくは参考文献[2]をご覧ください。