Postgres-BDR with Google Cloud Platform (PGDay Seoul 2016)

pgday.seoul 2016 에서 발표한 자료입니다.

아래의 running Postgres-BDR with Google Cloud Platform (1) ~ (4) 을 요약한 내용과 최종 테스트 결과가 정리되어 있습니다.

여러 복제 솔루션 중에서 Bucardo 가 Multi-master 를 지원하는데 Multi-Region 을 구성하여 테스트 해 본 결과, Manage node의 부하가 너무 심하게 걸리고 데이타 복제에 Delay 가 너무 심하게 발생하여 사용할 수 없을 정도였습니다.

Global 서비스 환경에서 Multi-Region 의 동기화를 위한 RDBMS 동기화 솔루션으로는 Postgres-BDR 이 안정적으로 동작하였으며, 네트워크 상태와 시스템 부하에 따라 Delay 가 발생하기도 하였지만, 어느 정도 시간이 지나면 데이타의 손실 없이 전송/수신함을 확인할 수 있었습니다.

RDBMS 중 Multi-Region 동기화를 지원하는 몇 안되는 솔루션으로, 글로벌 서비스를 할 계획이고, PostgreSQL을 사용하고자 한다면 사용을 고려해 보세요.

이상 공작명왕 입니다.

Running Postgres-BDR with Google Cloud Platform (4)

Running Postgres-BDR with Google Cloud Platform (4)

  • pgbench 를 이용한 Performance Test
  • 주의 사항
  1. 노드명 삭제 불가
  2. Global 시퀀스를 사용해야 함
  3. ddl 문 실행시 제한 조건
  4. 로그
  5. table 선택적 replication 사용 가능 ==> 추가 테스트 필요

* 테스트 마무리

pgbench 를 이용한 Performance Test

  • pgbench 테스트를 위한 테이블을 생성한다.
$ psql testdb
testdb=# create table tbl_bdr(c1 int);
CREATE TABLE
testdb=# \q
  • Performance Test 를 위해 준비해준다.
postgres@bdr-asia-2:~$ pgbench -U postgres -P 5432 -i testdb
NOTICE: table "pgbench_history" does not exist, skipping
NOTICE: table "pgbench_tellers" does not exist, skipping
NOTICE: table "pgbench_accounts" does not exist, skipping
NOTICE: table "pgbench_branches" does not exist, skipping
creating tables...
100000 of 100000 tuples (100%) done (elapsed 0.15 s, remaining 0.00 s).
vacuum...
set primary keys...
done.

-U postgres : postgres 유저로 접속
-P 5432 : 5432 포트로 접속
-i : 테스트준비
testdb : 디비로 testdb 를 이용하겠다.

postgres@bdr-asia-2:~$ pgbench -U postgres -p 5432 -S -c 10 -t 10000 testdb
starting vacuum...end.
transaction type: SELECT only
scaling factor: 1
query mode: simple
number of clients: 10
number of threads: 1
number of transactions per client: 10000
number of transactions actually processed: 100000/100000
latency average: 0.000 ms
tps = 11496.597122 (including connections establishing)
tps = 11520.436044 (excluding connections establishing)

-U postgres 유저로 로그인
-P 5432번 포트를 통해 접속
-S TCP-B 기준으로 테스트해서 결과를 얻겠다.
-c 동시연결 Client 는 10명
-t 트랜잭션을 10,000개로 하겠다.

부하를 주고 싶은 SQL 문을 만들어서 테스트 할 수도 있다.

postgres@bdr-asia-2:~$ cat test.sql
insert into tbl_bdr values (3);

test.sql 에는 부하를 주고 싶은 하나의 SQL 문만을 적어 놓는다.
반드시 한줄로 적어야 한다. 여러 줄 일때는 에러가 발생할 수 있다.

$ pgbench -U postgres -n -S -T 60 -c 10 -f test.sql testdb

10 동시 유저로 60초 동안 test.sql 의 SQL 문을 실행하라는 의미이다.

postgres@bdr-asia-2:~$ pgbench -U postgres -n -S -T 60 -c 10 -f test.sql testdb
transaction type: Custom query
scaling factor: 1
query mode: simple
number of clients: 10
number of threads: 1
duration: 60 s
number of transactions actually processed: 379920
latency average: 1.579 ms
tps = 6331.344284 (including connections establishing)
tps = 6332.955115 (excluding connections establishing)

실행하는 동안 vmstat 이나 sar, nmon 등으로 시스템 리소스를 모니터링 한다.


주의 사항 (0.9 에서 해당됨 / 1.0 에서는 확인이 필요함)

1. 노드명 삭제 불가

  • bdr.bdr_group_join 에 참여한 노드는 서버 이름을 변경하지 않으면 다시 등록이 안됨.

bdr.bdr_part_by_node_names()로 group에서 제외시켰음에도 불구하고,
bdr.bdr_nodes 목록에 여전히 등록되어 있으며, 같은 서버 이름으로는 이미 등록되어 있다고 등록이 안됨

  • 한 번 그룹에서 빠진 서버는 서버명을 변경해서 join하면 될거 같으나 클라우드 서버의 특성상 서버명 변경이 불가하기에 다른 서버를 생성하여 추가해야 함.
  • bdr.bdr_part_by_node_names() 함수의 버그로 보이며, 함수 실행 후 bdr.bdr_nodes 와 bdr.bdr_connections 의 정보를 확인하여 삭제해 주고, bdr_init_copy 명령어로 노드 추가를 할 수 있다.
  • 삭제는 노드 중 한 곳에서만 실행해도 된다.
select * from bdr.bdr_nodes;
delete from bdr.bdr_nodes where node_name='asia-node-003';
select * from bdr.bdr_connections;
delete from bdr.bdr_connections where conn_sysid='6189506087542501647';

2. Global 시퀀스를 사용해야 함

http://bdr-project.org/docs/stable/global-sequences.html
* 시퀀스를 사용하는 경우 글로벌 시퀀스를 사용해야 함. 그렇지 않으면fail over가 발생했을 경우 시퀀스 번호가 다른 노드에 자동 증가가 되지 않아서 오류가 발생함.
* 문법적으로 약간 다름
예) create sequence access_log_seq USING bdr;
* create sequence xxxx increment 1 minvalue 1 maxvalue 999999999999 start 1 cache 1;
구문과 같이 minvalue, maxvalue를 지정할수 없고cache 도 사용불가. minvalue는 1로 고정됨
* 데이터 타입이 전부 bigserial(bigint) 이어야 함.
* 시퀀스 번호가 순차적으로 생성 되지 않음.
예를 들어 노드1번이 1번부터 시작한다면 노드 2번은 100000번부터 노드3번은10000000부터 시작함. 내부적으로 트랜잭션 동기화 때문인거 같음

3. ddl 문 실행시 제약 조건

http://bdr-project.org/docs/stable/ddl-replication.html
* 다른 제약도 많지만 alter 문 실행시 default 값이 있을 경우 실행이 안됨
* 자세한 내용은 메뉴얼 참조

4. 로그

  • fail over 발생시 로그가 계속 출력됨. log rotate를 하지 않을 경우 문제가 될거 같음
  • (09/01 추가) 서버 fail 이 발생했을 경우에는 재빨리 replication group에서 제거해줘야 함.
  • 노드 제거 시에도 발생하게 되는데, bdr.bdr_part_by_node_names() 함수의 버그로 보이며 함수 실행 후, 제거된 노드에서 bdr.bdr_nodes 와 bdr.bdr_connections 의 정보를 확인하여 삭제하면 더 이상 추가 로그가 발생하지 않는다.
  • 삭제는 노드 중 한 곳에서만 실행해도 된다.
select * from bdr.bdr_nodes;
delete from bdr.bdr_nodes where node_name='asia-node-003';
select * from bdr.bdr_connections;
delete from bdr.bdr_connections where conn_sysid='6189506087542501647';

5. table 선택적 replication 사용 가능 ==> 추가 테스트 필요

http://bdr-project.org/docs/0.9.0/functions-replication-sets.html

  • 특정 table을 replicaion 하고 싶지 않을 경우
select bdr.table_set_replication_sets('user_info', '{}');

를 실행하면 user_info table 이 복제가 되지 않는다 table 속성을 보면 default 속성이 빠진걸 볼수 있음

  • 복원은 bdr.table_get_replication_sets() 사용

테스트 마무리

Cloud 서비스가 생기기 전에는 Global 서비스를 생각하는 기업은 별로 없었다.
Global 서비스라 하더라도 그 내용에 따라 각 지역별로 서버를 구성하고 독립적으로 운영하는 방식이 대부분이다.
하나의 단일 DB를 가지고 서비스를 한다는 것은 결코 쉽지 않은 일인데, Postgres-BDR 은 이걸 가능하게 해준다.

물론 장점만 있는 것은 아니다.
Postgres-BDR 은 Asynchronous 방식의 동기화를 지원하고 있다. Asnync 방식은 상황에 따라 Query 의 결과가 다를 수도 있음을 의미한다.
이런 동기화의 지연은 서비스에 따라 매우 치명적일 수 있다.
MySQL 에 비하면 PostgreSQL 은 아직 국내에선 낯설고 사용자도 많지 않은 상황인데다가 아직 국내에는 2ndQuadrant 의 협력사가 없어서 기술 지원도 문제가 될 수 있다.
그럼에도 불구하고 Postgres-BDR 이란 솔루션은 많은 장점을 가지고 있다고 생각한다.

개인적으로도 PostgreSQL 이 궁금해져서 PostgreSQL Korea User Group 의 Study 모임에도 참여하고 있다.
아직도 봐야할 것들이 많은 PostgreSQL 이지만 Global 서비스를 생각한다면 감히 사용해보길 추천한다.

Running Postgres-BDR with Google Cloud Platform (3)

Running Postgres-BDR with Google Cloud Platform (3)

  • Postgres-DBR 운영
        – 노드 추가
        – 노드 제거
  • Postgres-BDR 모니터링
  • 백업관련
  • 파티션 테이블 관리

Postgres-BDR 운영

Node Management Manual

노드 추가

  • 노드 추가는 pg_basebackup 으로 SOURCE로부터 전체 백업을 받아온 후, bdr_init_copy 라는 명령어를 이용한다.
  • 데이터가 계속 인입되는 runtime 환경에서 테스트한 결과, 노드 추가 후 group 에 join되어 곧 바로 동기화가 진행되었다.
  • 노드 추가에 영향을 주는 환경변수는 다음과 같다.
# 접속가능한 슬레이브의 접속수를 설정( 슬레이브 수 + 2)인거 같은데.. backup용 확실치 않음
max_wal_senders = 8
# 노드 + 1
max_replication_slots = 7
# BDR과 UDR 모두이 구성 데이터베이스 당 하나의 작업자 및 연결 당 하나의 작업자을 가지고 충분히 큰 값으로 설정해야합니다.
max_worker_processes = 10
  • 환경변수를 꼭 확인하고 신규로 추가할 서버에서 Postgres-BDR 을 설치하고 아래의 스크립트를 그대로 이용하면 된다.
# Created by Peter Yun. 2015-09-01.
#!/bin/bash
SOURCE="bdr-asia-2"
TARGET="bdr-asia-3"
NODENAME="asia-node-003"

sudo service postgresql stop
sudo rm -rf /var/lib/postgresql/9.4/main/*
sudo su -l postgres -c "pg_basebackup -h $SOURCE -U postgres -D /var/lib/postgresql/9.4/main -xlog -c fast -P"

sudo su -l postgres -c "/usr/lib/postgresql/9.4/bin/bdr_init_copy -d testdb -h $SOURCE -p 5432 \
--local-dbname=testdb \
--local-host=$TARGET --local-port=5432 \
--pgdata=/var/lib/postgresql/9.4/main \
--postgresql-conf=/etc/postgresql/9.4/main/postgresql.conf \
--hba-conf=/etc/postgresql/9.4/main/pg_hba.conf \
--node-name=$NODENAME "

sleep 10
sudo su -l postgres -c "tail -20 ~/bdr_init_copy_postgres.log"

# bdr 노드 추가 후 서버 중지
echo ""
echo ""
echo "bdr_init_copy_postgres.log 를 확인하여 이상없으면, bdr_init_copy 로 실행된 postgresql을 중지 하고 service 로 다시 띄운다."
echo "----------"
echo "sudo su -l postgres -c \"tail -20 ~/bdr_init_copy_postgres.log\""
echo "sudo su - postgres"
echo "/usr/lib/postgresql/9.4/bin/pg_ctl --pgdata=/var/lib/postgresql/9.4/main stop -m fast"
echo "exit"
echo "sudo service postgresql start"
echo "----------"

노드 제거

  • 함수로 쉽게 노드를 제거 할 수 있다고 하나, 실제로는 함수 실행 후 확인해보면 노드 정보가 남아있다. (select * from bdr.bdr_nodes;)
# node 하나만 제거
SELECT bdr.bdr_part_by_node_names(ARRAY['node-1']);
# 여러개의 노드를 한 번에 제거
SELECT bdr.bdr_part_by_node_names(ARRAY['node-1', 'node-2', 'node-3']);
# asia-node-003 제거
SELECT bdr.bdr_part_by_node_names(ARRAY['asia-node-003']);
  • 때문에 함수 실행 후 다음을 확인하여 남아있는 정보를 함께 지워준다.
# bdr_nodes 를 확인해서 제거한 노드가 남아 있으면 삭제해준다.
select * from bdr.bdr_nodes;
delete from bdr.bdr_nodes where node_name='asia-node-003';
# bdr_connections 를 확인해서 제거한 노드의 정보가 남아 있으면 삭제해준다.
select * from bdr.bdr_connections;
delete from bdr.bdr_connections where conn_sysid='6189502444603979480';

SELECT * FROM pg_replication_slots;
SELECT pg_drop_replication_slot('bdr_16386_6319248612493171876_2_16386__');

Postgres-BDR 모니터링

Monitoring manual

  • 노드 확인
SELECT * FROM bdr.bdr_nodes;
  • Monitoring connected peers using pg_stat_replication
SELECT * FROM pg_stat_replication;

SELECT
pg_xlog_location_diff(pg_current_xlog_insert_location(), flush_location) AS lag_bytes,
pid, application_name
FROM pg_stat_replication;
  • Monitoring replication slots
SELECT * FROM pg_replication_slots;

SELECT
slot_name, database, active,
pg_xlog_location_diff(pg_current_xlog_insert_location(), restart_lsn) AS retained_bytes
FROM pg_replication_slots
WHERE plugin = 'bdr';
  • Monitoring global DDL locks
select * from bdr.bdr_global_locks ;

백업 관련

  • 증분 백업
  • barman을 사용하여 증분 백업을 하고 싶지만… bdr를 사용할 경우, wal_level = ‘logical’ 옵션 때문에 증분 백업을 사용할수 없음
  • 증분 백업을 위해서는 wal_level 값이 ‘archive’, ‘hot_standby’ 값을 가져야만 함.

  • 노드 추가가 어렵지 않은 만큼 데이터 백업은 snapshot 또는 pg_dump, pg_basebackup 만 해도 괜찮을 듯 하다.


파티션 테이블 관리

  • 월별 range 파티션 사용 시 자동 파티션 생성 procedure 및 job 스케줄러 등록하여 관리가 가능한지 추가 확인 필요

To be continue …