bgworkerで超簡易クラスタ管理

  • 8
    Like
  • 0
    Comment
More than 1 year has passed since last update.

本記事では、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()関数についてです。

_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_flagsworker.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」に設定します。

postgresql.conf
shared_preload_libraries = 'pg_promoter'
# 以下は、pg_promoterに必要な設定項目です
pg_promoter.primary_conninfo = 'host=localhost port=15432'
pg_promoter.keep_alive = 5

上記の設定+レプリケーションの設定をします。

サーバの起動、bgwokerの起動

  1. マスタサーバの起動

pg_ctl start -D data

  1. スタンバイサーバの起動

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を使う際にご参考にしていただければと思います!
それでは良い週末を!

This post is the No.20 article of PostgreSQL Advent Calendar 2013