DB 이중화란 '기준이 되는 데이터베이스(Master)의 변경된 데이터를 물리적으로 떨어진 각각의 데이터베이스(Slave)에 동일하게 유지하여 관리하는 것'이라고 정의할 수 있습니다.
개인적인 프로젝트를 할 때는 이중화를 할 필요성을 그다지 느끼지 못했었는데, 실서비스에서는 데이터의 유실을 방지하거나 무중단 서비스를 위해서는 이중화가 필수입니다.
Master
)의 WAL(Write Ahead Log)에 Master
에서 발생하는 모든 작업을 로그로 기록합니다./var/lib/pgsql/data/pg_xlog
경로에 WAL
로그가 쌓이게 됩니다.Master
의 binary log
가 Postgresql Master
의 WAL
라고 할 수 있습니다.)Slave
)로 전달합니다.Slave
에서 받은 로그를 재실행함으로써 Master
와 데이터를 동일하게 유지할 수 있습니다.이렇게 데이터의 복제 과정을 구현하는 복제 방식으로는 2가지가 있습니다.
Log-shipping과 Streaming이 있습니다.
Master
의 WAL
파일 자체를 전송하는 방식으로 Async 방식만 가능합니다.Slave
에 WAL
파일이 제대로 복제되었다는 응답을 받지 않기 때문에 속도는 빠르지만 데이터의 유실 가능성이 있습니다.Log-shipping
방식은 Master
의 WAL
파일이 크기를 다 채워야만 Slave
로 전송이 일어나기 때문에 전송에 필요한 WAL
파일의 크기를 채우는 동안은 Master
와 Slave
는 동일하지 않은 데이터를 가지고 있습니다. 이때, Master
에 장애가 발생하게 되면 데이터의 유실이 발생합니다.Master
의 WAL
의 내용을 전송하는 방식으로 Async 방식과 Sync 방식 모두 가능합니다.Slave
에 전달한 내용이 제대로 복제되었다는 응답을 받기 때문에 속도는 느리지만 데이터의 유실 가능성이 낮습니다.WAL
파일의 최대 개수를 지정하는 postgresql.conf
의 wal_keep_segments
옵션의 값을 10으로 지정하였고.Slave
에 긴 시간의 서버 장애가 발생하였다고 가정해보겠습니다.Master
에는 장애가 발생하지 않았으므로 WAL
를 지속적으로 쌓습니다.Slave
의 장애가 해결되지 않았는데 Master
의 WAL
는 10번째 파일까지 쓰이고 나면 이후에는 가장 먼저 생성되었던 WAL 1(AAA)을 덮어쓰기 시작하고 덮어씌워진 WAL 1(KKK)에는 이전의 WAL 1(AAA)과는 다른 데이터를 기록하게 됩니다.Slave
의 장애가 해결되었고, Master
로 부터 WAL의 내용을 전송이 재개되지만, 덮어씌워진 WAL 1에 의해 데이터(AAA)가 유실되었습니다.Streaming
방식의 한가지 특징은 Master
에서는 WAL Sender Process
가 동작하며, Slave
에서는 WAL Receiver Process
가 동작합니다.Master
와 Slave
를 각각 사용해야 하므로 EC2 인스턴스를 2개 생성해주세요.
그리고 Master
로 사용할 인스턴스와 Slave
로 사용할 인스턴스에 각각 아래의 내용을 읽고 설치해주세요.
Master
만 먼저 세팅해주세요.pg_basebackup
명령을 사용해서 Master
의 설정 정보를 받아오고, 일부 수정하면서 세팅할거니까요.먼저, 두 대의 DB를 모두 동작 시킨다. sudo service postgresql start
(이전글에서 생성한 testuser 유저는 권한이 없다...)
vim /var/lib/pgsql/data/postgresql.conf
postgres.conf
설정 파일의 내용 중 아래의 내용처럼 각각 바꾸어 준다.
listen_addresses='*'
port = 5432
wal_level=hot_standby
wal_log_hint=on
archive_mode=on
archive_command='test ! -f /var/lib/pgsql/archive/%f && cp %p /var/lib/pgsql/archive/%f'
max_wal_senders=3
wal_keep_segments=64
hot_standby=on
logging_collector=on
추가하는 host의 ADDRESS에는 Slave
의 public ip를 입력한다.
이제 Slave
에서 해당 host로 접근할 수 있게 되었다.
위의 명령어들을 순차적으로 따라하면 Master
의 data 폴더가 Slave
에 정상적으로 복제된다.
Master
에서 복제한 postgresql.conf
중에서 Slave
에 맞게 수정해야 할 내용을 각각 바꾸어 준다.
listen_addresses='*'
port=5432
wal_level=hot_standby
wal_log_hints=on
#archive_mode=on
#archive_command='test ! -f /var/lib/pgsql/archive/%f && cp %p /var/lib/pgsql/archive/%f'
max_wal_senders=3
wal_keep_segments=64
hot_standby=on
logging_collector=on
recovery.conf
파일의 내용은 아래와 같이 입력해준다.
여기까지 작업이 끝났다면, Master
와 Slave
를 각각 재시작 시켜준다.
sudo service postgresql restart
SELECT pg_is_in_recovery();
쿼리를 실행해보면 Master의 경우 f, Slave의 경우 t로 나오면 정상적으로 이중화 세팅이 된 것이다.
CREATE TABLE t_replication (
name VARCHAR(20),
age INT
);
INSERT INTO t_replication VALUES('jwpark', 20);
SELECT * FROM t_replication;
정상적으로 하나의 데이터가 노출되었다면, 이중화가 정상적으로 된 것이다.
Postgresql의 이중화를 해보는데 무척 오랜 시간이 걸렸다.
필자가 설치한 Postgresql의 버전과 참고했던 링크에서의 버전이 다름으로써 설정파일에 replication 옵션이 없다던지, 필자의 실수(오타 or 누락)로 인한 것도 시간을 몹시 많이 잡아먹었다.
위에서 사용한 여러 명령들에 대하여 설명은 계속해서 추가할 예정이다.
어떻게든 실습을 먼저 진행해서 완료하고, 해당 명령을 이해하는 편이 공부하기에는 무척 좋은것 같다.
아무튼 이중화가 완료된 DB를 보고 나니 무척 뿌듯하다.
https://browndwarf.tistory.com/4
https://jinisbonusbook.tistory.com/70
https://it-sunny-333.tistory.com/122
https://bingbingpa.github.io/database/postgresql-replication/
https://idchowto.com/?p=44332
https://devegoist.tistory.com/1
글 잘봤습니다
마침 포스트그레스 이중화 업무가 내려왔는데 많은 도움이 되었습니다^^