TECH 으로 돌아가기
TECH HACKER NEWS 오늘 8분 읽기 41 READS

페타바이트 Postgres를 몇 시간에 백업하는 법: PlanetScale의 병렬 설계

페타바이트 Postgres를 몇 시간에 백업하는 법: PlanetScale의 병렬 설계
SOURCE IMAGE · HACKER NEWS

매 12시간마다, 수십만 QPS의 트래픽을 처리하는 데이터베이스 전체 상태를 프로덕션 쿼리에 영향을 주지 않으면서 일관되고 암호화된 스냅샷으로 바꿔야 한다. 백업은 대단히 중요하지만, 동시에 대다수 엔지니어가 가급적 신경 쓰고 싶어 하지 않는 영역이기도 하다. 데이터베이스 서비스 업체 PlanetScale이 블로그에서 공개한 샤딩 Postgres 백업 방식은, 페타바이트 규모 데이터를 수 시간 안에 초당 50GB가 넘는 속도로 처리하는 내부 구조를 드러낸다. 겉으로는 버튼 한 번이나 예약 스케줄로 끝나는 단순한 작업처럼 보이지만, 그 뒤에는 클라우드 인프라와 DBMS 도구를 정교하게 엮는 오케스트레이션이 있다.

프로덕션에 손대지 않는 백업 설계

PlanetScale의 샤딩 Postgres 제품인 Neki는 여러 개의 독립적인 Postgres 프라이머리 서버가 하나처럼 동작하는 구조다. 그래서 백업의 기본 단위 역시 개별 Postgres 서버 백업이며, 세 가지 방식 중 파일시스템 백업과 WAL(Write-Ahead Log) 재생을 결합한 방식을 사용한다. 문제는 이 작업이 상당한 IOPS와 연산을 잡아먹는다는 점이다. 프라이머리나 트래픽을 받는 리플리카에서 직접 수행하면 프로덕션 쿼리에 부담이 간다.

이를 피하기 위해 PlanetScale은 백업 전용 EC2 인스턴스를 샤드마다 하나씩 새로 띄운다. AWS나 GCP 같은 환경에서는 짧은 시간 동안 수십에서 수백 대의 인스턴스를 동적으로 확보했다가 반납할 수 있으므로, 약간의 비용을 지불하는 대신 프로덕션 영향을 최소화한다. 이렇게 준비된 백업 노드들이 실제 작업의 대부분을 떠맡는다.

복원, 따라잡기, 저장의 반복

정상 운영 상태에서의 흐름은 세 단계로 정리된다. 먼저 12시간 전에 S3(또는 GCS 같은 오브젝트 스토리지)에 저장해 둔 직전 백업을 각 샤드의 백업 노드로 스트리밍해 복원한다. 이 시점에 각 노드는 12시간 전 상태를 그대로 갖게 된다. 다음으로 그 사이에 쌓인 변경을 따라잡아야 하는데, 여기서 WAL 재생이 등장한다.

PlanetScale의 모든 Postgres는 wal-g로 WAL을 지속적으로 아카이빙하며, Neki에서는 샤드마다 별도의 WAL 아카이브 스트림을 갖는다. 다만 Postgres는 세그먼트가 완성된 뒤에야 WAL을 아카이빙하고, 트래픽이 세그먼트를 빨리 채우지 못하면 5분으로 설정된 archive_timeout이 세그먼트 전환을 강제한다. 즉 가장 최근 변경분은 아직 S3에 도달하지 않았을 수 있다. 그래서 대부분의 재생은 S3에서 처리하고, 마지막 몇 분치만 프라이머리에서 직접 스트리밍하는 하이브리드 방식을 쓴다. 모든 노드가 특정 시각 T까지 따라잡으면 WAL 복제를 멈춰 시점을 고정하며, T는 초 단위까지 기록되어 이 백업이 포함하는 정확한 시점을 남긴다. 이렇게 데이터가 뒤섞이지 않은 일관된 백업이 완성되면 암호화한 뒤 새로운 S3 버킷으로 보내 보관하고, 소임을 다한 백업 노드는 폐기한다.

최초 백업의 경우는 조금 다르다. 직전 백업이 없으므로 Postgres 기본 유틸리티인 pg_basebackup으로 각 샤드의 백업 노드를 시드한 뒤, 내구성 있는 백업 자체는 wal-g로 만든다. 초기 백업과 정상 백업의 포맷과 복원 절차를 동일하게 유지하기 위한 선택이다.

샤드 수만큼 빨라지는 병렬성

이 방식의 이점은 속도에서 뚜렷하게 드러난다. PlanetScale이 제시한 예시를 보면, 32테라바이트 데이터베이스가 20테라바이트로 압축된다고 할 때 복원·저장 등을 합친 총 전송량은 약 40,030GB에 이른다. 노드와 인터커넥트가 초당 500MB를 지속한다고 가정하면 샤딩하지 않은 단일 데이터베이스에서는 약 22시간이 걸린다. 하루 두 번 백업을 목표로 한다면 백업이 서로 겹쳐 복구 시점 목표(RPO)를 맞추기 어렵다. 반면 같은 데이터를 8개 샤드로 나눠 각 노드가 병렬로 처리하면 약 2.8시간으로 줄고, 32개 샤드라면 42분까지 내려간다. 100테라바이트를 100개 샤드에 분산하면 1테라바이트를 단일 샤드에서 백업하는 것과 사실상 같은 속도가 된다. 각 샤드가 자체 Postgres 프라이머리를 갖는다는 샤딩의 본질 덕분에, 검증된 단일 서버 백업을 샤드마다 반복하는 것만으로 규모에 비례한 확장이 가능해진다.

재해 대비를 넘어선 일상 운영 도구

주목할 점은 이 백업이 데이터 유실 대비용에 그치지 않는다는 것이다. 로컬 NVMe를 쓰는 Metal 데이터베이스에서는 리사이즈를 할 때마다 백업을 활용해 새 노드를 생성하고 따라잡게 하며, 이 과정은 백업 크기와 재생할 WAL 양에 따라 수 분에서 수 시간이 걸린다. 예기치 못한 장애로 노드를 교체할 때도 같은 메커니즘이 쓰인다. 샤드가 수백 개에 이르고 각각 여러 리플리카를 두면 일정 기간 내 노드 장애 확률이 통계적으로 크게 높아지므로, 백업을 이용한 자동 복구가 실질적인 운영 안전망이 된다.

PlanetScale은 Vitess로 라우팅하는 대규모 샤딩 MySQL도 운영하는데, 전체 골격은 유사하되 세부가 다르다. Postgres 기본 도구 대신 VTBackup을 쓰고, WAL 대신 MySQL 바이너리 로그 복제를 사용하며, 따라잡기 역시 S3와 프라이머리를 혼합하지 않고 프라이머리에서 직접 수행한다. 실무자 입장에서 이 사례가 시사하는 바는 분명하다. 백업을 프로덕션과 분리된 임시 컴퓨트에서 병렬로 수행하고, 오브젝트 스토리지를 대량 재생의 기반으로 삼되 최신 변경분만 원본에서 끌어오는 하이브리드 구조는 대규모 데이터베이스의 RPO 문제를 실제로 풀어내는 접근이다. 다만 이 모든 이점은 인스턴스를 반복적으로 띄웠다 내리고 데이터를 스토리지 안팎으로 옮기는 비용, 그리고 샤딩된 아키텍처라는 전제 위에서 성립한다는 점도 함께 읽어야 한다.

SOURCE · HACKER NEWS
원문 전체 보기 → https://planetscale.com/blog/massively-parallel-postgres-bac...
SHARE
처리 중...