本記事では、PostgreSQL9.3から新機能として入ったBackground Worker Processes(以下bgwoker)機能を使って bgworkerモジュールを自作する際のポイント 、また、実際に自作してみた 超簡易クラスタ管理モジュール「pg_promoter」 を紹介していきます。
bgwokerとは?
PostgreSQLで別々のプロセスでユーザ提供のコードが実行されるように、拡張することができる機能です。
特徴としては、
- 内部的にデータベースに接続することが出来る
- libpqと連携することによって、クライアントアプリケーションとしてもデータベースに接続することが出来る
- bgworkerを起動するタイミングを選択することが出来る(例えば、サーバの初期化終了時や、スタンバイで参照クエリが受け付けられる状態になった時など)
などがあります。
詳しくは公式ドキュメントをご参照ください。
自作bgworkerのポイント
bgworkerを自作するにあたり、実際に作成するときに感じたポイントを3つ紹介していきます。
##作りはじめる前に
PostgreSQLのcontribモジュールに worker_spi というモジュールがあるので、ぜひそれを参考にすると作りやすいです。
最低限必要な機能が揃っているので、それに手を加えていくだけで、自作bgworkerが作れます。
##_PG_init()
bgworkerのロード時に呼ばれる_PG_init()関数についてです。
void
_PG_init(void)
{
BackgroundWorker worker;
/* 必要なパラメータの定義などをする */
/* ここからはbgworkerについての設定 */
worker.bgw_flags = BGWORKER_SHMEM_ACCESS |
BGWORKER_BACKEND_DATABASE_CONNECTION;
worker.bgw_start_time = BgWorkerStart_ConsistentState;
worker.bgw_restart_time = BGW_NEVER_RESTART;
worker.bgw_main = pg_promoter_main;
worker.bgw_notify_pid = 0;
/* bgworkerの登録 */
snprintf(worker.bgw_name, BGW_MAXLEN, "pg_promoter");
RegisterBackgroundWorker(&worker);
}
ここでbgworker自体の設定をするのですが、その中でもworker.bgw_flags
とworker.start_time
についてを以下にまとめます。
- worker.bgw_flags (モジュールが要求する機能を設定)
値 | 内容 |
---|---|
BGWORKER_SHMEM_ACCESS | 共有メモリへのアクセスを許可 |
BGWORKER_BACKEND_DATABASE_CONNECTION | トランザクションや、クエリの実行が可能 |
- worker.start_time (bgworkerが起動するタイミングを設定)
値 | 内容 |
---|---|
BgWorkerStart_PostmasterStart | postgresの初期化が終わったら起動 |
BgWorkerStart_ConsistentState | 参照のみのクエリを実行するのを許可したら起動 |
BgWorkerStart_RecoveryFinished | 参照/更新クエリを実行すると起動 |
##機能の作成
機能の作成はbgworkerに限らずですが、 他のプログラムを参考にする とコードを書きやすいと思います。
次に紹介する「pg_promoter」では、pg_ctlやpgbench、postgres_fdwなどを参考にしながら作成しました。
超簡易クラスタ管理モジュール「pg_promoter」
bgworker機能を使って超簡易クラスタ管理モジュール「pg_promoter」というのを作ってみました。
「pg_promoter」は名前の通り、スタンバイサーバをただマスタにpromote(昇格)させるだけのシンプル(機能が足りないだけ?)なモジュールです。
主な特徴は以下の通りです。
- スタンバイサーバ側でのみ使用
- スタンバイサーバが参照クエリを受け付けられる状態になったタイミングで起動
- 設定項目は2項目(「マスタサーバへの接続情報」と「監視間隔」)
- 一定間隔でマスタサーバの死活監視を行う(スタンバイサーバ自身の死活監視は行わない)
- マスタサーバの死活監視はlibpqを使用してクライアントとして接続
- マスタサーバに異常があった場合は、スタンバイをマスタに昇格
- スタンバイサーバの昇格は内部でシグナルを送信
pg_promoterの使い方
pg_promoterのインストール
bgwokerとして登録するモジュールはcontribモジュールをインストールするときと同じように、make
,make install
でコンパイル、インストールします。
postgresql.confへ登録
bgworkerを登録する場合は、「shared_preload_libraries」に設定します。
shared_preload_libraries = 'pg_promoter'
# 以下は、pg_promoterに必要な設定項目です
pg_promoter.primary_conninfo = 'host=localhost port=15432'
pg_promoter.keep_alive = 5
上記の設定+レプリケーションの設定をします。
サーバの起動、bgwokerの起動
- マスタサーバの起動
pg_ctl start -D data
- スタンバイサーバの起動
pg_ctl start -D 2data
プロセスを見てみると、
14084 pts/2 S 0:00 /home/postgres/pgsql/9.3/bin/postgres -D data
14086 ? Ss 0:00 postgres: checkpointer process
14087 ? Ss 0:00 postgres: writer process
14088 ? Ss 0:00 postgres: wal writer process
14089 ? Ss 0:00 postgres: autovacuum launcher process
14090 ? Ss 0:00 postgres: stats collector process
14105 pts/2 S 0:00 /home/postgres/pgsql/9.3/bin/postgres -D 2data
14109 ? Ss 0:00 postgres: startup process waiting for 000000010000000000000003
14110 ? Ss 0:00 postgres: checkpointer process
14111 ? Ss 0:00 postgres: writer process
14112 ? Ss 0:00 postgres: stats collector process
14113 ? Ss 0:00 postgres: bgworker: pg_promoter
14114 ? Ss 0:00 postgres: wal receiver process streaming 0/3000090
14115 ? Ss 0:00 postgres: wal sender process postgres [local] streaming 0/3000090
となっており、14113 ? Ss 0:00 postgres: bgworker: pg_promoter
とbgworkerが起動していることがわかります。
つまり、PostgreSQLのバックグラウンドで「pg_promoter」がマスタ(PIDが14084)の死活監視を行っている状態となります。
スタンバイサーバの昇格
この状態でスタンバイサーバのプロセスをkillしてみます。
kill -SIGKILL 14084
すると数秒後に。。
LOG: received promote request
LOG: redo done at 0/20000F0
LOG: selected new timeline ID: 2
LOG: worker process: pg_promoter (PID 14113) exited with exit code 1
LOG: unregistering background worker "pg_promoter"
LOG: archive recovery complete
LOG: database system is ready to accept connections
LOG: autovacuum launcher started
とログが出て、昇格しました!
#ソースコード
記事だと分かりにくいので、「ぜひ試していただきたい!」と思い、githubとかに置く予定だったのですが、なかなか時間がなくてあげられてない状態です。
近々githubに置くので、ぜひ使ってみてください!
(2013/12/24 追記)
gitubに公開しました!
pg_promoter
URL : https://github.com/Masahiko-Sawada/pg_promoter
ぜひ使ってみてください!
#まとめ
今回はbgworkerの機能を使って、簡易的なクラスタ管理モジュールを作ってみました。
最初は興味本位で作っていましたが、作り込めばまあまあ使えるクラスタ管理モジュールができるのではと感じました。
まだPostgreSQL9.3がリリースされてから4ヶ月程度ですが、色々なことが出来る機能ですので、これから様々なモジュールが出てくると思います。
bgworkerについてあまり情報が少ないので、bgworkerを自作する時や、他のbgworkerを使う際にご参考にしていただければと思います!
それでは良い週末を!