9
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

PostgreSQLAdvent Calendar 2013

Day 20

bgworkerで超簡易クラスタ管理

Last updated at Posted at 2013-12-20

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

9
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?