본문으로 건너뛰기
12.1 스트리밍 복제

12.1 스트리밍 복제

Streaming replication은 PostgreSQL의 표준 물리 복제입니다. primary가 만든 WAL을 실시간으로 standby에 전달해 같은 상태의 복제본을 유지합니다. HA·읽기 부하 분산·DR(재해 복구)·백업 보조 등 운영의 기반입니다.

구조

    flowchart LR
  CLI["client"]
  PG1["primary"]
  WS["walsender"]
  WR["walreceiver"]
  PG2["standby (read-only)"]
  CLI2["read clients"]

  CLI -->|read·write| PG1
  PG1 -->|WAL 변경 발생| WS
  WS -->|TCP 스트림| WR
  WR --> PG2
  CLI2 -->|read only| PG2

  classDef pri fill:#ede9fe,stroke:#6d28d9,color:#3b0764,stroke-width:2px
  classDef std fill:#d1fae5,stroke:#047857,color:#064e3b
  classDef mid fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a
  class PG1 pri
  class PG2 std
  class WS,WR mid
  
  • primary에서 walsender가 standby의 walreceiver에 WAL을 보냄
  • standby의 startup process가 받은 WAL을 재생해 상태 유지
  • standby는 read-only — hot_standby = on일 때 SELECT 가능

기본 설정

primary

# postgresql.conf
wal_level = replica           # 최소
max_wal_senders = 10
wal_keep_size = 1GB           # 슬롯 없는 standby의 안전망
max_replication_slots = 10
# pg_hba.conf
hostssl  replication  repl_user  10.0.0.0/8  scram-sha-256
CREATE ROLE repl_user WITH REPLICATION LOGIN PASSWORD 'secret';

standby 초기화

primary의 데이터를 복사한 뒤 standby로 띄움.

# standby 호스트에서
sudo -u postgres pg_basebackup \
  -h primary.example.com -U repl_user \
  -D /var/lib/pgsql/17/data \
  -X stream -P -R --slot=standby1

# 자동으로:
# - standby.signal 파일 생성
# - postgresql.auto.conf에 primary_conninfo, primary_slot_name 추가
sudo systemctl start postgresql-17

두 가지 동기 모드

모드synchronous_commit
비동기 (async)local 또는 off — 기본
동기 (sync)on/remote_write/remote_apply + synchronous_standby_names

비동기

# primary
synchronous_commit = local

primary commit이 standby 응답을 안 기다림. 빠르지만 primary 손실 시 마지막 N초 트랜잭션 손실 가능합니다.

동기

# primary
synchronous_commit = on
synchronous_standby_names = 'ANY 2 (s1, s2, s3)'   # 3대 중 2대 응답 (quorum)
표현의미
FIRST 1 (s1, s2)우선순위 — s1 응답 우선, 안 되면 s2
ANY 1 (s1, s2)둘 중 하나 응답 (quorum)
ANY 2 (s1, s2, s3)셋 중 둘 응답
'*'모든 standby

Quorum 권장: 2 of 3 형태. 한 standby가 죽어도 primary가 계속 동작합니다. FIRST 1 (s1)처럼 단일 standby에 의존하면 그 standby가 죽을 때 primary commit이 영원히 멈춥니다.

synchronous_commit 단계별

primary fsyncstandby writestandby flushstandby apply
off비동기
local동기
remote_write동기동기
on동기동기동기
remote_apply동기동기동기동기

remote_apply는 standby에서 query까지 같은 결과 보장 — 비용 큽니다. 대부분 운영은 on 또는 remote_write.

standby 동작 확인 — primary 측

SELECT pid, application_name, client_addr, state,
       sent_lsn, write_lsn, flush_lsn, replay_lsn,
       write_lag, flush_lag, replay_lag, sync_state
  FROM pg_stat_replication;
컬럼의미
statestreaming 정상
sent_lsnprimary가 보낸 위치
write_lsnstandby가 받아쓴 위치
flush_lsnstandby가 fsync한 위치
replay_lsnstandby가 재생한 위치
*_lag각 단계 지연 시간
sync_statesync / async / quorum / potential

replay_lag가 분 단위로 자라면 standby 부하 또는 단일 트랜잭션 적용 지연.

standby 측 확인

SELECT pg_is_in_recovery(),
       pg_last_wal_receive_lsn(),
       pg_last_wal_replay_lsn(),
       pg_last_xact_replay_timestamp();

pg_last_wal_receive_lsnpg_last_wal_replay_lsn의 차이가 재생 lag.

cascading replication

standby가 또 다른 standby에 WAL을 보낼 수 있습니다.

    flowchart LR
  P["primary"] --> S1["standby 1<br/>(streaming)"]
  S1 --> S2["standby 2<br/>(cascading)"]
  S1 --> S3["standby 3"]

  classDef p fill:#ede9fe,stroke:#6d28d9,color:#3b0764
  classDef s fill:#d1fae5,stroke:#047857,color:#064e3b
  class P p
  class S1,S2,S3 s
  

장점: primary 부하 ↓. 단점: S1 장애 시 S2·S3가 같이 끊김.

운영 시 주의

주의메모
primary의 wal_keep_size가 너무 작음 + 슬롯 없음standby 연결 끊기면 WAL 잘림 → 재구축 필요
슬롯이 있으면 안전, but primary pg_wal/ 가득 차는 위험모니터링 필수
동기 단일 standby그 standby 장애 시 primary 정지 — quorum으로
standby가 매우 뒤처짐hot_standby_feedback·single big tx 검토
timeline 불일치옛 standby를 새 primary에 붙일 때

비동기 standby의 데이터 손실

primary가 죽었을 때 비동기 standby가 가지지 못한 WAL이 있을 수 있습니다. 그 standby를 promote하면 그 분량의 트랜잭션은 사라집니다. 동기 복제만이 commit 응답 = 손실 없음을 보장.

운영 패턴:

  • 동기 1대(같은 데이터센터) + 비동기 1~2대(DR 리전) = 손실 방지 + DR 모두

정리

  • streaming replication = WAL 실시간 전송, standby가 같은 상태 유지
  • 비동기는 빠르지만 손실 가능, 동기는 안전하지만 비용
  • quorum 동기(ANY 2 (s1, s2, s3))가 운영 표준
  • 진단: pg_stat_replication (primary), pg_is_in_recovery + replay_lsn (standby)
  • cascading으로 primary 부하 분산 가능
  • 슬롯 없는 standby는 wal_keep_size가 안전망

다음 절(12.2)에서는 standby 연결 끊김에도 WAL을 보장하는 복제 슬롯을 봅니다.