Triggerでpostgresqlからmongodbへのデータ同期案

このエントリーをはてなブックマークに追加
こんにちわ、開発エンジニアのou.gです。
今回triggerでpostgresqlのデータをmongodbへの同期方法についてまとめました。

登場人物



処理流れ
  postgresqlの同期対象テーブルのレコードの変更があったら、triggerで検知して、 gearmanのclientがデータ変更情報をgearmanに送ります。
  gearmanのworkerが変更データを拾って、加工(必要があれば)して、mongodbに反映します。

pggearmanについて
  postgresqlの中に使われるgearman clientはGearman PostgreSQL Functionsです。
最後のリリースは2009年で、9.1以降のpostgresqlには動けません。
  postgresql9.1以降にも使えるpggearmanを作ってgithubに上げました。

pggearmanのインストール
git clone https://github.com/wangyuehong/pggearman.git
cd pggearman
make && make install

postgresqlの設定ファイルに下記の設定を追加
pggearman.default_servers = 'localhost'

同期対象データベースに /usr/local/postgresql/share/contrib/pggearman.sql をロード

Trigger作成

  • まず、triggerで呼ばれるUDFを作成

CREATE OR REPLACE FUNCTION send_to_gearman()
RETURNS trigger
AS $$
BEGIN
  PERFORM gman_do_background('replicate2mongo', CAST(row_to_json(NEW.*) AS text));
  RETURN NULL;
END;
$$ LANGUAGE plpgsql;


  • 次、同期対象テーブルにtriggerを定義

CREATE CONSTRAINT TRIGGER r2m_pgbench_accounts
AFTER UPDATE or INSERT -- 例なので、DELETE未実装
ON pgbench_accounts
DEFERRABLE INITIALLY DEFERRED -- transaction成功commitのみ実行させる
FOR EACH ROW
EXECUTE PROCEDURE send_to_gearman();


  • 次、Gearmanのworkerを作成

my $worker = Gearman::Worker->new;
$worker->job_servers('127.0.0.1:4730');

my $mongo_connection = MongoDB::Connection->new('host' => 'localhost:27017');
my $mongo_db         = $mongo_connection->get_database('foo');
my $mongo_collection = $mongo_db->get_collection('pgbench_accounts');

$worker->register_function(
    replicate2mongo => sub {
        my ($job) = @_;
        my $json = decode_json($job->arg);
        ##ここで、いろんなデータ加工ができる
        $mongo_collection->update({ 'aid'    => $json->{aid} },
                                  { '$set'   => $json },
                                  { 'upsert' => 1 });
        return 1;
    }
);

$worker->work while 1;

pgbench_accountsのレコードの変更があったら、すぐmongodbのfoo.pgbench_accountsに反映されます。

パーフォーマンス検証

pgbenchでの検証結果

session数
trans per second
(triggerなし)
trans per second
(triggerあり)
avg trans time(triggerなし)
avg trans time(triggerあり)
1
1303.178338
1009.327054
0.763004
0.98487
4
2626.154359
1316.355209
1.51575
3.02863
8
2430.173718
1358.721837
3.27649
5.86531

まとめ
この案は簡単だけど、triggerの定義で結構パフォーマンス落ちるので、弊社製品には使われなかったが、他のとろこで使えるかもしれないので、まとめて書きました。


次の記事
« Prev Post
前の記事
Next Post »
Related Posts Plugin for WordPress, Blogger...