LoginSignup
25
35

More than 5 years have passed since last update.

PostgreSQL マルチマスタ(BDR)を試してみた

Last updated at Posted at 2016-04-19

PostgreSQL BDR (Bi-Directional Replication)とは

PostgreSQL9.0 から Streaming Replication が実装されています。マスタからDBの更新情報(WAL) を複数のスレーブに対して送信・適用する事で、マスタとスレーブのデータ同期を行います。
マスタは参照/更新が可能ですが、スレーブでは参照のみで更新を行う事はできません。
また、マスタ側が障害となった場合SPOFとなる為、PGPOOL等の外部ツールにより可用性を向上させる必要があります。

9.4 からは logical replication が追加されました。BDRはこの logical replication を使うことで、1マスタNスレーブ構成だった Streaming Replication を Nマスタに拡張することができる外部ツールです。
BDR のマスタはそれぞれ、参照/更新が可能です。

image

環境

・Cent OS 6.7(2台)
・PostgreSQL9.4

インストール

マニュアルを参考にインストールします。BDR 0.10.0 Documentation

事前準備_node1&node2
# chkconfig --level 2345 iptables off
# service iptables stop
# groupadd -g 301 postgres
# useradd -d /home/postgres -m -u 301 -g postgres postgres
# id postgres
uid=301(postgres) gid=301(postgres) groups=301(postgres)
インストール準備_node1&node2
# cd /usr/local/src
# wget http://yum.postgresql.org/9.4/redhat/rhel-6-x86_64/pgdg-centos94-9.4-2.noarch.rpm
# rpm -ihv pgdg-centos94-9.4-2.noarch.rpm
# yum check-update
# yum groupinstall "Development Tools"
# yum install yum-utils openjade docbook-dtds docbook-style-dsssl docbook-style-xsl
# yum-builddep postgresql94
PostgreSQL9.4をインストール_node1&node2
# git clone -b bdr-pg/REL9_4_STABLE git://git.postgresql.org/git/2ndquadrant_bdr.git postgresql-bdr
# mkdir /usr/local/pgsql
# chown -R postgres:postgres /usr/local/pgsql
# chown -R postgres:postgres /usr/local/src/postgresql-bdr
# su - postgres
$ cd /usr/local/src/postgresql-bdr
$ ./configure --prefix=/usr/local/pgsql --enable-debug --with-openssl
$ make -j4 -s install-world
$ exit
#
BDRをインストール_node1&node2
# id
uid=0(root) gid=0(root) groups=0(root)
# cd /usr/local/src
# git clone -b bdr-plugin/REL0_9_STABLE git://git.postgresql.org/git/2ndquadrant_bdr.git bdr-plugin
# chown -R postgres:postgres /usr/local/src/bdr-plugin
# su - postgres
$ cd /usr/local/src/bdr-plugin
$ PATH=/usr/local/pgsql/bin:"$PATH" ./configure
$ make -j4 -s all
$ make -s install
$ ll /usr/local/pgsql/bin/ | grep bdr
-rwxr-xr-x 1 postgres postgres   928885 Apr 18 06:29 bdr_dump
-rwxr-xr-x 1 postgres postgres   169288 Apr 18 06:29 bdr_init_copy
-rwxr-xr-x 1 postgres postgres     2399 Apr 18 06:29 bdr_initial_load
-rwxr-xr-x 1 postgres postgres    89440 Apr 18 06:29 bdr_resetxlog
⇒上記の4ファイルが存在する事を確認

PostgreSQL設定

PostgreSQLを起動させる準備_node1
$ PATH=/usr/local/pgsql/bin:"$PATH"
$ mkdir /usr/local/pgsql/bdr
$ initdb -D /usr/local/pgsql/bdr/node1 -A trust -U postgres
PostgreSQLを起動させる準備_node2
$ PATH=/usr/local/pgsql/bin:"$PATH"
$ mkdir /usr/local/pgsql/bdr
$ initdb -D /usr/local/pgsql/bdr/node2 -A trust -U postgres
PostgreSQL設定_node1
$ cd /usr/local/pgsql/bdr
$ cat >> ./node1/postgresql.conf <<EOF
listen_addresses = '*'
shared_preload_libraries = 'bdr'
wal_level = 'logical'
track_commit_timestamp = on
max_connections = 100
max_wal_senders = 10
max_replication_slots = 10
max_worker_processes = 10
log_error_verbosity = verbose
log_min_messages = debug1
log_line_prefix = 'd=%d p=%p a=%a%q '
bdr.default_apply_delay=2000   # milliseconds
bdr.log_conflicts_to_table=on
EOF

$ cat >> ./node1/pg_hba.conf <<EOF
host    all             all           XX.XX.0.0/16    trust
local   replication     postgres                      trust
host    replication     postgres      XX.XX.0.0/16    trust
host    replication     postgres      ::1/128         trust
EOF
※XX.XX.XX.XX…node1とnode2が通信可能となるように設定
PostgreSQL設定_node2
$ cd /usr/local/pgsql/bdr
$ cat >> ./node2/postgresql.conf <<EOF
listen_addresses = '*'
shared_preload_libraries = 'bdr'
wal_level = 'logical'
track_commit_timestamp = on
max_connections = 100
max_wal_senders = 10
max_replication_slots = 10
max_worker_processes = 10
log_error_verbosity = verbose
log_min_messages = debug1
log_line_prefix = 'd=%d p=%p a=%a%q '
bdr.default_apply_delay=2000   # milliseconds
bdr.log_conflicts_to_table=on
EOF

$ cat >> ./node2/pg_hba.conf <<EOF
host    all             all           XX.XX.0.0/16    trust
local   replication     postgres                      trust
host    replication     postgres      XX.XX.0.0/16    trust
host    replication     postgres      ::1/128         trust
EOF
※XX.XX.XX.XX…node1とnode2が通信可能となるように設定
PostgreSQL起動・DB作成_node1
$ pg_ctl -l /usr/local/pgsql/bdr/node1/postgres.log -D /usr/local/pgsql/bdr/node1 -w start
$ createdb -U postgres bdrdemo
PostgreSQL起動・DB作成_node2
$ pg_ctl -l /usr/local/pgsql/bdr/node2/postgres.log -D /usr/local/pgsql/bdr/node2 -w start
$ createdb -U postgres bdrdemo
CREATE_EXTENSION実行_node1
$ psql -U postgres bdrdemo
CREATE EXTENSION btree_gist;
CREATE EXTENSION bdr;
SELECT bdr.bdr_group_create(local_node_name := 'node1',node_external_dsn := 'host=node1_ip port=5432 dbname=bdrdemo');

SELECT bdr.bdr_node_join_wait_for_ready();
\q
※node1_ipのIP
CREATE_EXTENSION実行_node2
$ psql -U postgres bdrdemo
CREATE EXTENSION btree_gist;
CREATE EXTENSION bdr;
SELECT bdr.bdr_group_join(local_node_name := 'node2',node_external_dsn := 'host=node2_ip port=5432 dbname=bdrdemo', join_using_dsn := 'host=node1_ip port=5432 dbname=bdrdemo');

SELECT bdr.bdr_node_join_wait_for_ready();
\q
※node1_ipのIP
※node2_ipのIP
BDR状態確認_node1,node2
$ psql -U postgres bdrdemo
select * from bdr.bdr_nodes;

node_sysid   |node_timeline|node_dboid|node_status|node_name|              node_local_dsn          |           node_init_from_dsn
-------------+-------------+----------+-----------+---------+--------------------------------------+-------------------------------------------
XXXXXXXXXXXXX|            1|     16385|r          |node1    |host=node1_ip port=5432 dbname=bdrdemo|
XXXXXXXXXXXXX|            1|     16385|r          |node2    |host=node2_ip port=5432 dbname=bdrdemo|host=node1_ip port=5432 dbname=bdrdemo
\q
※node1_ipのIP
※node2_ipのIP

PostgreSQL BDR動作確認

node1_テーブルを作成してインサート
$ psql -U postgres bdrdemo
CREATE TABLE bdr_test (c1 INT, c2 text, PRIMARY KEY (c1));
INSERT INTO bdr_test VALUES (1, 'test1');
INSERT INTO bdr_test VALUES (2, 'test2');
SELECT * FROM bdr_test;
 c1 |  c2
----+-------
  1 | test1
  2 | test2
(2 row)
node2に反映されているか確認
$ psql -U postgres bdrdemo
SELECT * FROM bdr_test;
 c1 |  c2
----+-------
  1 | test1
  2 | test2
(2 row)
node2でデリート
$ psql -U postgres bdrdemo
DELETE FROM bdr_test WHERE c1 = 2;
SELECT * FROM bdr_test;
 c1 |  c2
----+-------
  1 | test1
(1 row)
node1で確認
$ psql -U postgres bdrdemo
SELECT * FROM bdr_test;
 c1 |  c2
----+-------
  1 | test1
(1 row)

更新の重複

・マルチマスタにすると、PrimaryKeyとなっている一意の項目に対し、node1とnode2で同時に更新しようとした場合に競合が発生します。
それを回避する為、BDRは複数のnodeで重複しない値を生成するGlobal Sequencesを提供しています。Global Sequencesを使うと各nodeで1000個ずつの値を割り振り、node1は1~1000、node2は1001~2000の値が使われるようになります。

最後に

・あっさりとPostgreSQLのマルチマスタが組めました。今までは、可用性を高める方法として、streaming replicationかPGPOOL等でやってましたが、PostgreSQL BDRも十分に使えると思いました。

25
35
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
25
35