PostgreSQL 고가용성

0. 들어가며

데이터베이스 시스템이 장애 없이 잘 사용되고 있다는 지표를 고가용성 High Availability 이라는 용어로 설명 합니다. 예를 들어서 고가용성 99.999 % 라는 말은 1년 가운데, 99.999 %는 서비스 장애가 없음을 말합니다. (1년에 약 5분정도 됩니다.)

이 글은 이 부분에 대한 이야기입니다.

어떻게 하면 데이터베이스 서비스가 1년을 운영하면서 5분 미만의 장애 시간을 유지 할 수 있는지에 대한 답은 의외로 데이터베이스 밖의 문제를 함께 고민해야 합니다.

전력, 네트워크, 하드웨어, OS 등 이 부분의 문제가 모두 위에서 말한 고가용성에 대한 설계가 충실하지 않다면, 데이터베이스의 고가용성 또한 의미가 없겠죠.

그래서, 고가용성은 데이터베이스 관리자에게는 다소 무리가 있는 부분입니다. PostgreSQL 공식 설명서에서도 이 부분을 이미 잘 알고 있기에, 앞에서 이야기 한 데이터베이스 범위를 벗어나는 부분에 대한 고가용성을 잠깐 언급할 뿐, 대부분의 이야기를 데이터베이스 스트리밍 복제에 촛점을 맞춥니다.

1. OS 기반 고가용성

클라우드 기반으로 인프라 시스템들이 옮겨가면서 OS 입장에서 고가용성은 하이퍼바이저가 알아서 잘 합니다. 데이터베이스 관리자 입장에서는 그저 하이퍼바이저가 데이터베이스 서버가 운영될 OS가 OS 장애로 멈추면 똑 같은 OS가 어떻게든 다시 그 역할을 수 있는지만 확인하면 될 것입니다. (더 나아가 이제는 응용프로그램(데이터베이스 서버 프로그램) 컨테이너 기반으로 OS 부분도 전혀 고려하지도 않는 추세로 흘러가기는 합니다.)

하지만, 그래도 아직까지는 그래도 OS 클러스터링이라는 개념은 클라우드 환경이 아닌 곳에서는 유효합니다. 각 OS 종류 별로 수 많은 OS 클러스터를 구현 하는 시스템 소프트웨어들이 있습니다.

1.1. 공유디스크

데이터베이스 시스템에서 사용하는 저장 공간으로는 고가의 SAN 스토리지를 사용하거나 그보다 좀 저렴한 iscsi 스토리지를 사용합니다. NAS 기반 nfs 파일 시스템을 데이터 저장 공간으로는 절대로 사용하지 않는 것이 관례입니다. nfs 파일 시스템은 잦은 읽기 쓰기 환경에서는 속도와 안전성을 보장하지 않기 때문입니다. 

여기서 하나 관심을 가져야 하는 부분은 OS 차원의 고가용성을 구현 할 때 절체(fail over) 시 장애가 발생한 운영 중이였던 노드에 대한 처리를 전원 차원에서 할 것인지, 마운트 된 디스크 차원에서 할 것인지를 결정 해야 하며, 일반적으로 장애 노드를 꺼버리는 방식인 파워팬싱을 기법을 이용합니다. 이 경우는 대부분의 클러스터링 솔루션이 제공하기 때문에 문제가 되지 않는데, 디스크의 마운트를 차단하겠다는 디스크 팬싱인 경우는 클러스터링 솔루션과 스토리지의 궁합이 딱 맞아야 가능합니다. 

디스크 팬싱 기법으로 절체를 하는 경우 파워 팬싱 보다 얻는 장점이 훨씬 많지만, (장애 원인 파악, 절체 시간 등등) 앞에서 말한 솔루션과 스토리지의 궁합이 맞지 않아 사용할 수 없는 상황이 생기기도 합니다. 잘 살펴야 합니다.

공유 스토리지 기반 고가용성을 고려한다면, 스토리지, 각 DB 서버를 운영할 노드, 그리고 그 공유 스토리지의 백업 정책도 함께 고려해야 합니다.

1.2. Heartbeat 네트워크

흔히 Heartbeat 망이라고 불리는, 노드에 문제가 있지를 체크하는 이 네트워크의 중요성은 스토리지 선택만큼이나 중요하지만, 이 부분은 기술적인 부분 보다는 복불복인 경우가 더 많습니다. 기계는 언젠가는 고장이 날 것인데, 그 고장이 언제 날 것인가? 이것이 문제이기 때문입니다. 일반적인 권고 사항은 Heartbeat 네트워크는 각기 다른 이더넷 인터페이스 카드의 포트를 묶어(bonding) OS 입장에서 하나의 이더넷 인터페이스 포트를 사용하는 방식 - 여기서 중요한 것은 bonding 작업시 반드시 물리적으로 다른 인터페이스 카드여야 한다는 것입니다 - 과 OS 클러스터 솔루션에서 heartbeat 체크 포트의 이중화를 제공하고 있어 그냥 단순하게 여러 heartbeat ip를 나열하는 방식이 있습니다. 물론 이 때도 안전을 위해 각각 다른 인터페이스 카드의 IP를 사용해야 겠지요.

일반적으로 이 망은 패쇄망으로 패쇄망 전용 스위치를 쓰기도 하고 그냥 단순히 랜선만 서로 연결해서 쓰기도 합니다.

1.3. 리눅스 기반 OS 클러스터 소프트웨어

리눅스에서는 전통적으로 corosync + pacemaker 기반으로 모든 설정을 각각 설정해서 구현했으나(데비안 계열은 아직도 이런 방식으로 처리를 할 듯), 요즘은 각 배포판 별로 제공하는 통합 솔루션을 제공합니다. 대표적으로는 RHCS, OEL 클러스터 등이 있습니다. 이 부분에 대한 상세 구축 방법에 대해서는 이 글의 범위를 벗어나서 간단한 소개로 마칩니다. 이들 모두 PostgreSQL과 만날 때 구축 작업자는 다음에서 소개하는 PostgreSQL 리소스 관리부분에 신경을 써야 합니다.

1.4. PostgreSQL 리스소 관리

대부분의 클러스터링 솔루션의 fail over 작업은 각 리소스를 체크하는 스크립트의 리턴값을 보고 판단합니다. 

이때 HA 솔루션이 사용하는 스크립트는 기본적으로 pg_ctl status 명령을 이용하는 것이 대부분입니다.
이 명령의 작업 내용은 해당 데이터베이스 postmaster 프로세스가 실행중인가만 확인을 합니다. 

가장 깔끔한 PostgreSQL 리소스 확인용 스크립트는 psql -c "select relname from pg_class where relname = 'pg_class'" 명령의 리턴값이 정상(0)인가를 판단하는 것입니다. 이 명령어가 정상적으로 실행되었다 함은 데이터베이스가 서비스 시작 중이든가, 중지 중이든가, 싱글 모드로 실행되고 있다든가 하는 상황이 아니라 정상적으로 서비스를 할 수 있음을 의미하기 때문에, pg_ctl status 명령으로 확인하는 것보다 더 확실합니다. 

흔히 select version() 쿼리가 정상적으로 실행되었다면, 데이터베이스가 정상이다고 판단할 수도 있겠지만, 데이터베이스 가장 기본 테이블인 pg_class 테이블을 읽을 수 있는 상황인지까지 확인하는 것이 안전합니다. 

그런데, 이 작업이 해당 호스트의 여러 상황에 관계되어 반응이 아주 느리거나, 아에 반응하지 않는 경우도 발생합니다. 위에서 언급한 psql 명령어를 스크립트에서 사용하게 되면 이 확인 작업의 timeout 제어를 할 수 없게 됩니다. 

결국 이 확인 스크립트는 다음과 같은 독립된 스크립트로 작성하는 것이 좋습니다. 
$ cat check_pg.py
#!/usr/bin/env python

import os,sys,select,time
import psycopg2

def wait(conn):
    timeout_sec = 5;
    starttime = time.time();
    while 1:
        if (time.time() - starttime) > timeout_sec:
            raise psycopg2.OperationalError("Select Timout");
        state = conn.poll()
        if state == psycopg2.extensions.POLL_OK:
            break
        elif state == psycopg2.extensions.POLL_READ:
            select.select([conn.fileno()], [], [], timeout_sec)
        elif state == psycopg2.extensions.POLL_WRITE:
            select.select([], [conn.fileno()], [], timeout_sec)
        else:
            raise psycopg2.OperationalError("bad state from poll: %s" % state)


try:
    conn = psycopg2.connect(dbname='test', async=1)
    wait(conn);
    cur = conn.cursor()
    cur.execute("select relname from pg_class where relname = 'pg_class'")
    wait(conn);
    res = cur.fetchone()
    cur.close()
    conn.close()
except psycopg2.OperationalError:
    sys.exit(1)

python 코드로 작성되었으며, python에서 PostgreSQL 데이터베이스를 다루는 가장 대표적인 psycopg2 모듈을 이용합니다. 아주 간단한 스크립트인데, 비동기 방식으로 접속하고, 쿼리를 실행하기 위해서 약간 복잡해 졌습니다. 

실무에서 사용하려면, 해당 connect() 함수의 매개변수로 적당히 접속 정보를 수정해 주셔야 하고, 이 때 tcp 접속까지 확인해 보려면 host 값도 지정해야 할 것입니다. 
다음 timeout 설정을 5초로 지정했습니다. 이 부분에 대해서 꽤 많은 이야기가 필요한데, 이 부분은 생략하겠습니다. 

HA 설계에서 '5초 안에 데이터베이스가 아주 간단한 쿼리 결과를 던지지 않으면 이 상황을 절체 상황으로 보아야 하는가?' 라는 질문에 대한 답으로 위 5초 설정에 대한 결정을 해야 합니다. 즉, 데이터베이스 서버가 아무리 바빠도 위 쿼리의 결과를 1시간 뒤에 던져도 그 상황은 절체 상황이 아니다고 설계하려면, timeout 설정을 빼야 할 것입니다. 

2. PostgreSQL 스트리밍 복제

OS 기반 고가용성 설계와 함께 같이 고민해야 하는 것이 절체 되고 새롭게 운영 될 데이터베이스 서버의 자료로 공유 디스크를 쓸 것인지, 디스크 복제된 새로운 디스크를 쓸 것인지를 결정해야 합니다. 

안전한 공유 디스크를 사용하려면 비용이 많이 들지요. 서버군 스토리지 장비를 생각하면 됩니다. 그와 달리 디스크 복제 기법을 이용한다고 하면, 이 또한 몇가지로 나뉩니다. 커널 기반 디스크 블록 단위 복제를 하는 디스크 복제 솔루션을 사용하거나(대표적인 솔루션이 DRBD입니다) PostgreSQL 내장 기능인 스트리밍 복제 기능을 사용합니다.  대부분의 커널 기반 디스크 블록 단위 복제 솔루션은 RDBMS 환경에서 사용하기에는 아직까지는 조금 부족합니다. 

물론 전통적으로 PostgreSQL 스트리밍 복제 기능을 제공하기 전부터 여러 복제 기법이 있었지만, 여기서는 스트리밍 복제에 대해서만 다루겠습니다. 왜냐하면, slony나, bucardo 같은 솔루션들은 서비스 성질에 특화되어 범용적인 복제 기법이라기  보기 힘들기 때문입니다. 

그래서, 미들웨어 기반 고가용성 설계를 위해서 먼저 PostgreSQL 트랜잭션 로그 스트리밍 복제 환경을 먼저 구축하고, 이 기반 위에 미들웨어 쪽 설정을 살펴보기로 합니다.

2.1. 운영 서버 설정

PostgreSQL 스트리밍 복제 설정은 크게 실재 운영 중인 서버가 스트리밍 복제 기능을 이용할 수 있도록 환경 설정을 바꾸어 주는 일과 대기 서버를 구축해서 운영 서버와 연결 시키는 두가지 일로 나뉩니다. 

스트리밍 복제 기능을 이용하기 위해서는 운영 서버쪽에서는 또 세가지 작업이 진행 되어야 합니다. 

첫번째는 스트리밍 복제 작업을 하는 DB 유저를 만드는 일. psql 에서 진행합니다.
CREATE ROLE forrepl LOGIN REPLICATION;

두번째, 그 DB 유저가 대기서버에서 운영 서버로 접속 가능하도록 접근 권한을 부여하는 일. 이 작업은 $PGDATA/pg_hba.conf 파일을 수정하는 작업입니다.
# forrepl 사용자는 데이터베이스 접속을 막음
local   all             forrepl                                reject
host    all             forrepl        0.0.0.0/0               reject
# localhost 복제 테스트용
local   replication     forrepl                                trust
#운영서버 IP
host    replication     forrepl         192.168.0.10/32        trust
#대기서버 IP
host    replication     forrepl         192.168.0.11/32        trust
위와 같이 운영 서버와 대기 서버 모두 서로 접속 할 수 있도록 설정해 둡니다. 대기 서버를 구축할 때 운영 서버의 환경을 그대로 가져와서 만들기 때문에 운영 서버가 다시 대기 서버로 운영 구축 될 때를 위해서 미리 자기 IP도 함께 설정해 두는 것이 좋습니다. 여기서 주의할 사항은 PostgreSQL 호스트 기반 접근제어는 pg_hba.conf 파일에 등록된 순서로 체크합니다. 즉, 해당 파일의 앞부분에서 이미 열어 두었다면, 뒤 부분에서 막아도 아무런 소용이 없습니다.  

세번째는 $PGDATA/postgresql.conf 파일을 수정해서 서버의 환경설정을 바꾸는 일입니다. 이 설정은 기본설정에서 변경하는 경우라면 대부분의 설정이 데이터베이스 서버를 재실행 해야하는 설정임으로 실 운영 환영이라면, 반드시 이 부분을 알고 있어야 합니다. 
설정해야할 환경 설정값은 다음과 같습니다. 
listen_address = '*'
wal_level = 'hot_standby'
max_wal_senders = 3
wal_keep_segments = 64
hot_standby = on
max_wal_senders 값은 운영서버를 바라보는 대기서버의 개수보다 조금 많게 지정해 줍니다. wal_keep_segments 값은 archive_mode 값이 off 되어 있다면, 서버가 재 시작되고 난 다음부터 대기서버를 구축 할 때까지 쌓일 트랜잭션 로그 조각 파일의 개수보다 많아야 합니다. 일단 checkpoint_segments 값의 서너배 정도로 넉넉하게 지정하세요. 이럴 만한 공간이 $PGDATA/pg_xlog 쪽에 없다면, archive_mode 값을 on 해서 버릴 트랜잭션 로그 조각들을 따로 보관해 두어야 합니다. 이 값에 대해서는 관리자가 잘 성해야 대기서버를 구축 할 때 좀 더 편해집니다.

환경 설정이 끝나면, 서버를 재실행해야 합니다. 

추가로 사용하는 서버가 9.4 이상이라면, 새롭게 등장한 복제 슬롯 기능을 이용하기 위해서 데이터베이스 슈퍼유저 권한은 데이터베이스에 접속해서, 다음 명령을 실행해서 복제 슬롯을 하나 만들어 둡니다. 
SELECT * FROM pg_create_physical_replication_slot('ha_slot');

2.2. 대기 서버 설정

대기 서버 구축 작업은 운영 서버 설정보다 조금 더 복잡합니다. 

첫번째 작업은 운영 서버를 그대로 백업해서 대기 서버에 운영에 필요한 파일들을 해당 호스트에 가져오는 것입니다. 가장 손 쉬운 방법은 pg_basebackup 명령을 이용하는 것입니다. 
$ mkdir -m 700 /data/mydb
$ cd /data/mydb
$ pg_basebackup -h 192.168.0.10 -U forrepl -D . -R
대기 서버가 실행될 호스트로 쉘 로그인을 해서 구축할 $PGDATA 디렉토리를 만들고, 그 디렉토리로 가서 위 명령을 실행합니다.  이때 주의할 사항은 운영 서버에서 독자적인 테이블스페이스를 사용하고 있다면, 그 테이블스페이스 안의 파일들이 저장될 상위 디렉토디들이 그대로 대기서버에도 미리 있어야 합니다.

운영 서버의 자료가 많다면, 이 작업 또한 오래 걸립니다. 실 운영 환경이라면, 이 작업 시간을 감안해서 구축 계획을 세워야합니다. 

두번째 작업은 대기 서버로 실행 되도록 환경 설정 파일을 약간 고칩니다. pg_basebackup 에서 -R 옵션을 주면 대기 서버에 $PGDATA/recovery.conf 파일을 만들어줍니다. 그런데, 이 설정이 switch over (정상적인 상황에서 운영 서버를 바꾸는 작업) 나, 9.4 버전에서 나온 복제 슬롯 기능에 대한 고려가 없어 이 부분을 추가해줍니다. $PGDATA/recovery.conf 파일에 다음 내용을 추가합니다.
recovery_target_timeline = 'latest'
# 버전이 9.3 이하라면 다음 줄은 주석처리하세요
primary_slot_name = 'ha_slot'
마지막으로 이 recovery.conf 파일을 운영서버 쪽 어느 한 곳에 두고 primary_conninfo 설정값에 있는 마스터 서버 주소를 바꾸어줍니다. (나중에 운영 서버를 대기 서버로 재구축 없이 바로 사용하려고 할 때 이 파일이 미리 있으면 편합니다.)

대기 서버를 실행합니다. 잘 실행 되는지 서버 로그를 살펴보고 문제가 있으면 알아서 풀어야 합니다. 워낙 다양한 실패 경우가 있어서 일일히 나열하기는 힘들 것 같습니다. (Do It Yourself!)

2.3. 모니터링

DB 입장에서 스트리밍 복제가 잘 작동되고 있는가를 살펴보는 일은 아주 간단합니다.  OS의 ps 명령으로 sender 프로세스(운영 서버에 있음)와, receiver 프로세스(대기 서버에 있음)가 정상 작동 하는가만 살펴보면 됩니다. ps 명령을 사용할 수 없는 환경이라면, SQL 쿼리문으로 운영 서버에서는 pg_current_xlog_location() 함수를, 대기 서버에서는 pg_last_xlog_receive_location() 함수를 이용해서, 각각의 현재 트랜잭션 ID가 무엇이고, 그것이 대기 서버에 잘 반영 되었는가를 살펴보면 됩니다. 

그런데, 실무에서는 이 지표가 단지 스트리밍 복제가 잘 되고 있는지만 살펴보는 것일 뿐 잘 안되고 있는 상황에서는 vmstat, netstat, iostat 같은 여러 OS 모니터링 도구를 이용해서 OS 상황을 진단해야 합니다.  스트리밍 복제 관련 문제는 DB 자제의 문제라기 보다는 외부 문제가 원인인 경우가 대부분이기 때문입니다.

3. 미들웨어 기반 고가용성

OS 기반 고가용성은 일반적으로 두 개의 노드로 구성 해서 서로 상대 노드를 감시 하는 방식을 이용합니다. 이런 경우의 가장 큰 문제점은 상대 노드 감시 결과 각각 서로 운영 서버가 되어버리는 split brain 사고입니다. 공유 디스크를 사용하는 경우는 이 사고로 각각 마운트 되어버리는 사고로 이어지기도 하고, 디스크 복제 기반에서는 서로 다른 내용이 디스크에 저장되기도 하는 사고로 이어집니다.  이런 치명적인 문제점을 안고 있음에도 불구하고, OS 기반 고가용성 기법이 서비스 전체적인 관점에서 보면 가장 손쉬운 방법이기 때문에 가장 보편적으로 사용되는 방법입니다.

한편, 고가용성 설계의 다른 방법으로 서비스 전체 시각에서 보면 DB와 응용 프로그램 사이 고가용성 처리을 담당하는 미들웨어를 두면, 일단 split brain 사고는 막을 수 있습니다. 또한 응용 프로그램 쪽 설계를 다시 하지 않아도 됩니다.

개념은 간단합니다. 응용 프로그램에서는 데이터베이스 사용 설정이 단 하나이고(pgpool 인경우는 디비 접속 정보, jboss datasource 인 경우는 JNDI 이름), 해당 미들웨어에서는 운영서버가 정상이면 쿼리를 운영 서버로 전달 하고, 쿼리를 전달 할 수 없는 상황이면 대기 서버로 쿼리를 전달하는 기법입니다. 

3.1. pgpool

pgpool 솔루션을 사용하는 경우는 pgpool 데몬을 응용프로그램이 실행되는 호스트에 둘 것인지, DB 서버가 운영 되고 있는 호스트에 둘 것인지를 결정할 때, 가장 일반적인 방법은 각 미들웨어 서버에 각각의 pgpool 데몬을 실행하는 것입니다. 

설정 방법은 위에서 설명한 PostgreSQL 스트리밍 복제 환경을 먼저 구축하고, 
pgpool.conf.sample-master-slave 파일을 가지고 pgpool.conf 파일을 하나 만들어서 사용합니다. 

수정한 값은 다음과 같습니다.(각 노드별 등록 작업, backend_hostN 이하 환경 설정들도 미리 해야합니다.)
load_balance_mode = off
master_slave_sub_mode = 'stream'
failover_command = 'ssh postgres@%H "pg_ctl -D %R promote"'
load_balance 기능은 껐습니다. 여기서 중요한 것은 부하 분산이 아니라, 데이터베이스 이중화를 통한 고가용성을 이야기하고 있기 때문입니다.  아직까지도 pgpool 데몬은 그다지 튼튼한 데몬이 아니기 때문에, pgpool 데몬의 부하 분산 기능은 실무에서는 얻는 이점보다 장애처리 항목이 더 늘어나며, pgpool 자체의 쿼리 파싱 비용을 더 추가하기 때문에 권장하지는 않습니다. (이 부분은 지극히 글쓴이의 주관적인 견해입니다. 참고만 하세요. pgpool의 풀링 기능도 그리 썩 깔끔하지 않기는 마찬가지이긴 합니다.)

그외, health_check 관련 설정도 하면 좋겠죠. pgpool 의 특성이 이 health_check 기능을 켜두지 않으면 데이터베이스를 사용하는 쿼리를 실 서버로 보낼 때 그 쿼리가 실패하면 해당 노드를 빼는 방식을 취합니다. 그래서, health_check 기능을 켜두면 응용프로그램에서 데이터베이스 서버를 이용하지 않더라도 스스로 확인해서 미리 사용가능한 환경을 만들어둡니다. 

pgpool의 노드 관리 특징이 있는데, 이 점을 잘 알고 있어야 합니다.  관리 노드 목록에서 빠진 서버는 관리자가 수동으로 다시 등록하지 않으면(attach) pgpool 데몬이 재실행되기 전까지 사용할 수 없습니다.

failover_command 설정의 목표는 새로 운영 서버가 될 호스트에서 pg_ctl promote 명령을 실행하는 일입니다. 이 작업이 핵심인데, 이 부분에서 생각해야 할 것이 꽤 있습니다. pg_ctl promote 명령은 그 서버를 운영 서버로 쓰겠다는 것을 의미합니다. 
그러기 위해서는 다음이 모두 만족되어야 합니다. 
  • 기존 운영 중이던 서버 노드로는 더 이상이 쿼리가 유입되지 말아야 한다. pgpool을 단지 failover 기능만 이용하기 위해서 AP 쪽에서는 독립된 데이터베이스 연결을 사용하고 있다면, 반드시 주의해야 합니다. 
  • promote 작업은 스트리밍 복제와 관계 없이 그냥 운영 서버로 전환된다. 즉 스트리밍 복제가 완벽하게 동기화 되지 않아도 운영 서버로 전환되기 때문에 동기화 문제에 대한 고려를 해야 한다. (위와 같이 pgpool의 failover 기능만 이용하는 경우라면, 반드시 손실 되는 자료가 없도록 하려면 응용 프로그램 쪽에서 쿼리가 실패할 경우 그 쿼리를 재실행하는 방법을 마련해 두어야 한다.)
  • 이 failover 에 대한 failback 정책을 결정해야 한다. - pgpool을 사용하는 경우라면, failback 작업은 관리자가 직접 개입해서 또 다른 대기 서버를 재구축하고, pgpool에 노드 등록을 직접하는 작업이 반드시 있어야 하기 때문에, 한 번 failover 작업이 진행되면 그 떨어져 나간 노드로 다시 failover 작업이 자동으로 진행되지 않도록 하는 것이 제일 무난하다.
추가로 pgpool 사용시 하나의 팁.
pgpool은 데몬 모드로 실행하는 것 보다, pgpool 터미널 모드로 실행하고, 출력을 로그 파일로 저장하고, 백그라운드로 전환하는 것이 좋습니다.  로그파일 처리가 조금 불편하지만, 그래도 데몬 모드 보다는 안정적으로 작동하더군요. 
pgpool -D -n

3.2. jboss datasource

jboss의 datasource connection pool 확장 모듈을 사용해서 데이터베이스 작업을 한다는 전제로 이야기합니다. spring 같은 별개의 프래임워크로 datasource를 관리하는 경우에 대해서는 저도 잘 몰라서 이 글에서 다룰 수가 없습니다.  tomcat 경우는 기본 제공하고 있는 datasource connection pool 확장 모듈이 그다지 안정적이지 않습니다. (idle connection 처리부분에 버그가 있어 사용에 신경을 써야 합니다. 요즘의 최신 버전에서는 이 문제가 고쳐졌는지는 모르겠습니다.)

3.3. django-failover


4. 마치며

이 글에서 중요한 사실은 PostgreSQL active-standby, master-slave 서버를 구축한다고 그 데이터베이스의 가용성이 높아지는 것은 아니라는 것입니다.