PostgreSQL 실전 강좌 #8 복제와 고가용성: 스트리밍 복제, 읽기 분산, 페일오버
여기까지의 모든 이야기는 서버 한 대 안이었습니다. 그러나 한 대에는 두 가지 한계가 있습니다. 죽으면 서비스가 멈추고(가용성), 읽기 부하가 몰리면 더 키울 곳이 없습니다(확장). 두 문제의 표준 수단이 복제, 즉 같은 데이터를 가진 서버를 여러 대 두는 것입니다. 원리를 알아 두면 관리형 서비스의 옵션들(RDS Multi-AZ vs 읽기 전용 복제본에서 다룬 그 선택지들)이 “무엇을 사 주는 상품인지"가 선명해집니다.
원리: WAL을 흘려보내기 #
PostgreSQL은 모든 변경을 커밋 전에 WAL(Write-Ahead Log)이라는 순차 로그에 먼저 씁니다(장애 복구의 근거이자, 다음 편 PITR의 재료입니다). 스트리밍 복제는 이 WAL을 네트워크로 스탠바이 서버에 실시간으로 흘려보내고, 스탠바이가 그것을 재생하는 것입니다. 바이트 수준의 사본이 만들어지므로 물리 복제라고도 부릅니다. 스탠바이는 읽기 전용 쿼리를 받을 수 있어서(hot standby), 대기 장비이면서 동시에 읽기 분산의 수단이 됩니다.
비동기가 기본값, 그리고 복제 지연 #
기본 동작은 비동기입니다. 프라이머리는 커밋을 스탠바이 도착과 무관하게 완료하므로 쓰기 성능에 부담이 없지만, 두 가지 대가가 있습니다.
- 장애 시 유실 창: 프라이머리가 죽는 순간 아직 안 넘어간 WAL만큼의 커밋이 사라질 수 있습니다.
- 복제 지연(replication lag): 스탠바이는 언제나 약간 과거입니다. 평소 밀리초 수준이지만 부하에 따라 초 단위로 벌어집니다.
지연의 실무 증상이 read-your-writes 문제입니다. 사용자가 글을 쓰고(프라이머리) 목록을 새로 고쳤는데(스탠바이) 자기 글이 없습니다. 읽기 분산을 도입하는 순간 애플리케이션이 감당해야 하는 문제로, 통상의 해법은 “쓴 직후의 읽기는 프라이머리로 보낸다"는 라우팅 규칙입니다. 지연 관측은 프라이머리의 pg_stat_replication 뷰로 합니다.
SELECT client_addr, state,
pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) AS lag_bytes
FROM pg_stat_replication;유실 창을 못 견디는 도메인(결제 등)에는 동기 복제(synchronous_commit)가 있습니다. 스탠바이 확인 후에 커밋을 완료하므로 유실이 없어지는 대신, 모든 커밋에 왕복 지연이 붙고 스탠바이 장애가 쓰기 장애로 번집니다. “전부 동기"가 아니라 트랜잭션 단위로 골라 쓰는 것도 가능하므로, 필요한 곳에만 값을 치르는 것이 정석입니다.
페일오버: 승격은 쉽고, 판단이 어렵습니다 #
프라이머리가 죽으면 스탠바이를 승격(promote)시켜 새 프라이머리로 만듭니다. 승격 자체는 명령 하나입니다. 어려운 것은 그 앞뒤입니다. 죽었다는 판단(네트워크 순단인지 진짜 장애인지), 애플리케이션 접속 전환, 그리고 최악의 사고인 스플릿 브레인(옛 프라이머리가 살아 있는데 새 프라이머리도 쓰기를 받아 데이터가 갈라지는 것)의 방지입니다. 그래서 자동 페일오버는 스크립트가 아니라 합의 기반의 오케스트레이터에 맡깁니다. 자체 운영의 사실상 표준이 Patroni(분산 합의 스토어로 리더를 관리)이고, 관리형 서비스의 Multi-AZ 자동 페일오버는 바로 이 층을 통째로 사 주는 상품입니다. RDS vs 자체 운영의 계산에서 이 항목의 무게가 큰 이유입니다.
논리 복제: 테이블 단위로 골라 보내기 #
물리 복제가 “클러스터 전체의 바이트 사본"이라면, 논리 복제는 테이블 단위로 변경 내용(행의 INSERT/UPDATE/DELETE)을 발행(publication)하고 구독(subscription)하는 방식입니다. 쓰임새가 다릅니다. 일부 테이블만 분석용 DB로 보내기, 메이저 버전이 다른 서버로의 복제(무중단 업그레이드의 재료, 다음 편에서), 여러 DB의 데이터 통합 같은 자리입니다. 스탠바이 전체를 만드는 것이 목적이면 물리, 데이터의 일부를 다른 모양의 시스템으로 나르는 것이 목적이면 논리라고 기억하면 됩니다.
정리 #
- 복제의 원리는 WAL 스트리밍입니다. 바이트 사본(물리)이 만들어지고, 스탠바이는 읽기를 받을 수 있습니다.
- 기본은 비동기이고, 대가는 유실 창과 복제 지연입니다. 읽기 분산은 read-your-writes 라우팅과 세트입니다.
- 유실을 못 견디는 트랜잭션에만 동기 복제의 값을 치릅니다. 전부 동기는 과합니다.
- 페일오버의 본체는 승격이 아니라 판단·전환·스플릿 브레인 방지입니다. 자체 운영은 Patroni, 관리형은 Multi-AZ가 그 답입니다.
- 테이블 단위·버전 교차는 논리 복제의 자리입니다. 다음 편, WAL을 재료로 한 백업·PITR·업그레이드로 시리즈를 마무리합니다.