주요 컨텐츠로 이동
Lakebase

대규모 환경에서 빠른 복구를 위한 Lakebase Postgres 브랜치 기반 복원

Lakebase Postgres가 느린 데이터베이스 복구를 거의 즉각적인 브랜치 기반 복구로 대체하여 몇 초 만에 100 TB를 복구하는 방법

작성자: Cassie Murray , Carlota Soto

  • 기존의 데이터베이스 복구는 매우 느리고 규모가 커짐에 따라 확장성이 떨어지며, 새로운 컴퓨팅을 프로비저닝하고 대규모 스냅샷을 다운로드하고 로그 파일을 재실행하는 동안 종종 몇 시간의 다운타임이 발생합니다.
  • Lakebase Postgres는 데이터를 복사하는 대신 분리된 스토리지의 변경 불가능한 이력을 가리켜 데이터베이스를 즉시 복구하는 메타데이터 작업인 브랜치 기반 복구를 도입합니다.
  • 100 TB 데이터베이스를 복구하는 데 몇 초밖에 걸리지 않아 복구가 거의 즉각적으로 이루어지며, AI 에이전트가 브랜칭 및 실행 취소 워크플로를 원활하게 처리할 수 있도록 지원합니다.

 

관리형 OLTP에서 복구는 항상 고통스러울 정도로 느렸으며, 규모가 커질수록 더 느려집니다. 이는 다운타임 비용이 가장 많이 발생하는 대규모 프로덕션 데이터베이스가 복구하는 데 가장 오랜 시간 대기해야 함을 의미하는 경우가 많습니다.

일반적인 해결 방법은 어렵고 비용이 많이 들며 위험합니다. 추가 복제본, 추가 환경, 심지어 복구 시 DBA의 개입까지 필요하지만, 이 역시 완벽한 보호를 보장하지는 않습니다. 정상적인 복제본으로의 페일오버는 장비가 다운되었을 때는 도움이 되지만, 잘못된 쓰기가 이미 대기 서버(standby)에 반영된 경우에는 도움이 되지 않습니다. 이 경우 여전히 복구가 필요하며, 복구에는 몇 시간의 다운타임이 발생할 수 있습니다.

이러한 고통은 기존 관리형 OLTP 시스템의 아키텍처 때문에 발생합니다. 컴퓨팅과 스토리지가 하나의 장비로 제공되므로 복구는 새 인스턴스 프로비저닝부터 시작됩니다(이미 대기가 시작됨). Postgres가 해당 볼륨에서 실행되는 동안 스냅샷은 오브젝트 스토리지에 있으므로 스냅샷을 디스크로 가져와야 합니다(추가 대기). 그런 다음 WAL 리플레이를 통해 스냅샷 시점부터 정확한 복구 타임스탬프까지의 격차를 메워야 합니다(더 많은 대기). 데이터베이스가 커질수록 이 과정은 더 느려지고 비용이 많이 듭니다.

Lakebase Postgres 아키텍처는 모놀리스를 깨고 복구 메커니즘을 변경합니다. Lakebase에서는 컴퓨팅과 스토리지가 분리(decoupled)되어 있으며, 데이터베이스 이력이 즉시 참조 가능한 방식으로 오브젝트 스토리지에 이미 보관되어 있습니다. 이 아키텍처에서 복구는 데이터를 새 디스크로 복사하지 않습니다. 대신 타임스탬프에서 브랜치를 생성하기만 하면 되며, 이는 몇 시간이 걸리는 복사 및 리플레이 작업이 아닌 간단한 메타데이터 작업입니다.

실질적으로 데이터베이스가 100 TB에 달하더라도 복구 시간은 몇 초 수준으로 단축됩니다. 게다가 에이전트가 수행할 수 있을 정도로 매우 간단합니다.

image6.png

기존 OLTP 복구 경로 (및 한계점)

기존 Postgres의 PITR(시점 복구)은 파일의 베이스 백업과 해당 백업 이후의 모든 항목에 대한 아카이브된 WAL이라는 두 가지 요소로 구성됩니다. Amazon RDS와 같은 관리형 Postgres 환경에서 해당 백업은 일반적으로 오브젝트 스토리지에 있는 스냅샷입니다.

“백업에서 복구”하여 특정 시점 T로 되돌리는 것은 실제로는 다음 세 단계로 구성된 프로세스입니다.

  1. 새 인스턴스 배포
  2. T 이전의 가장 최근에 사용 가능한 스냅샷 복구
  3. 해당 스냅샷부터 T까지 WAL 리플레이

1. 새 인스턴스 배포

여기에는 최소한 기본(primary) 인스턴스와 동일한 컴퓨팅 및 스토리지 볼륨(결합됨)을 제공하는 작업이 포함됩니다. 작은 인스턴스는 몇 분 안에 가동될 수 있지만, 대용량 EBS 볼륨이 있는 대형 인스턴스는 대개 더 오래 걸리므로 복구 프로세스를 시작하기도 전에 대기해야 합니다.

2. 스냅샷에서 복구

RDS 스냅샷은 S3에 있으므로, “복구”란 해당 스냅샷을 오브젝트 스토리지에서 가져와 Postgres 디스크로 옮기는 것을 의미합니다.

이 프로세스는 크기가 클 때 느리기 때문에, RDS는 복구된 인스턴스를 available 상태로 만들기 전에 이 작업이 완료될 때까지 기다리지 않습니다. 대용량 볼륨의 경우, 대부분의 테이블 및 인덱스 페이지가 여전히 S3에 있는 동안 이 작업이 수행됩니다. 하지만 사용 가능하다고 해서 작업 세트(working set)가 Postgres 볼륨에 있음을 의미하지는 않습니다. 쿼리가 아직 로컬에 없는 블록을 터치하면, 볼륨은 백그라운드에서 나머지 데이터를 계속 채우는(hydrating) 동안 해당 블록을 S3에서 즉시 가져옵니다.

이러한 유형의 쿼리는 내부 점검에는 괜찮지만 프로덕션 환경에는 적합하지 않은 지연 시간을 동반합니다. 복구는 실제로 필요한 데이터가 볼륨에 상주할 때만 완료되며, 대규모 데이터베이스의 경우 이는 빠르지 않습니다. 데이터베이스가 클수록 더 많은 시간(몇 시간 단위)이 소요됩니다.

3. T까지 WAL 리플레이

스냅샷은 스냅샷 시점을 기준으로만 일관성을 유지합니다. T에 도달하려면 Postgres는 해당 스냅샷 이후에 아카이브된 트랜잭션 로그를 여전히 리플레이해야 합니다. 리플레이에 걸리는 시간은 스냅샷과 T 사이에 얼마나 많은 일이 발생했는지에 따라 달라집니다. 1시간 전의 스냅샷은 어젯밤의 스냅샷보다 훨씬 빠를 것입니다. 또한 쓰기 작업이 많은 날이었다면 리플레이해야 할 WAL이 많을 것입니다. 이 역시 (인스턴스가 여전히 S3에서 데이터를 채우고 있는 상황 외에도) 오랜 대기를 의미합니다.

상당한 다운타임 창

데이터베이스가 작지 않은 한, PITR은 거의 항상 몇 시간이 걸리는 작업입니다. 모놀리스를 프로비저닝하고, S3에서 스냅샷을 가져오고, WAL을 리플레이하고, 트래픽을 처리할 수 있을 만큼 충분한 볼륨이 로컬에 확보될 때까지 기다려야 합니다.

그 전체 기간 동안 다운타임이 발생할 수 있습니다. 기본(primary) 인스턴스가 다운되고 복제본에 여전히 정상적인 데이터가 있는 경우 상태가 양호한 고가용성(HA) 복제본이 구원해 줄 수 있습니다. 하지만 PITR로부터 구해주지는 못할 수 있으므로 삭제된 테이블과 잘못된 쓰기가 이미 대기 서버(standby)에 반영되어 있을 수 있습니다.

느린 데이터베이스 복구는 고통스럽습니다

 

설문조사에서 1TB+ 프로덕션 Postgres를 운영하는 50명의 개발자에게 복구 경험에 대해 질문했습니다.

  • 59%가 지난 12개월 동안 심각한 프로덕션 장애를 경험했습니다.
  • 30%는 3시간 이상 다운타임을 겪었으며, 일부는 반나절을 넘겼습니다.
  • 단 21%만이 60분 이내에 복구되었습니다.

이는 잠재적인 비즈니스 악영향을 초래했습니다.

  • 40%가 중대한 비즈니스 중단을 보고했습니다.
  • 52%가 해당 장애로 인한 고객의 부정적인 피드백을 확인했습니다.
  • 72%는 장애가 다시 발생했을 때 빠르게 복구할 수 있을지에 대해 “어느 정도만 자신한다”고 느꼈습니다.

브랜치 기반 복구가 제시하는 새로운 경로

image4.png

Lakebase Postgres에서는 현대적인 아키텍처를 통해 복구를 위한 다른 경로를 제공합니다.

컴퓨팅과 스토리지의 분리

컴퓨팅과 영구 스토리지는 서로 분리되어 있으며 WAL로 연결됩니다. 컴퓨팅은 Postgres를 실행합니다. 즉, SQL 실행, 쿼리 계획, MVCC 적용, 잠금 관리, WAL 생성 등 일반적인 Postgres 작업을 모두 수행합니다. 하지만 데이터의 영구 복사본을 직접 소유하지는 않습니다.

스토리지는 영속성과 이력을 소유하며, 이 작업은 세 가지 고유한 구성 요소에 의해 세 부분으로 나뉘어 실행됩니다.

  • Safekeepers는 컴퓨팅으로부터 WAL을 수신합니다. 정족수(quorum)의 safekeepers가 WAL 레코드를 승인하면 트랜잭션이 영구적으로 보존됩니다.
  • Pageserver는 WAL을 Postgres가 읽는 페이지로 변환합니다. 지정된 LSN에서 지정된 키에 대한 모든 페이지를 재구성할 수 있습니다.
  • 오브젝트 스토리지는 불변의 장기 이력을 보관합니다. 컴퓨팅은 이를 직접 읽지 않으며, pageserver가 그 중간에 위치합니다.

image3.png

쓰기 작업이 들어오면:

  1. Postgres가 메모리에서 행을 변경하고 WAL을 생성합니다.
  2. 컴퓨팅이 해당 WAL을 safekeepers로 스트리밍합니다.
  3. 정족수가 이를 승인하면 트랜잭션이 영구적으로 보존됩니다.
  4. 이후 pageserver가 해당 WAL을 페이지 버전으로 변환합니다.
  5. 해당 버전은 불변의 이력으로 오브젝트 스토리지에 저장됩니다.

주소 지정이 가능한 타임라인으로 저장되는 이력

이 설계에서 쓰기 경로는 흥미로운 형태를 취합니다. 위의 아키텍처는 트랜잭션 커밋과 페이지 구체화(materializing)를 분리하는데, 이는 더 간단히 말해 기존 페이지 버전이 절대 덮어씌워지지 않음을 의미합니다. 데이터베이스의 이력은 변경하는 단일 복사본이 아니라 가리킬 수 있는 타임라인으로 쌓이게 됩니다.

Lakebase에서의 복구는 특정 시점의 브랜치입니다

기존 경로에서 복구는 주로 과거 상태를 별도의 인스턴스로 재구축하는 것을 의미합니다. 하지만 Lakebase를 사용하면 참조할 수 있는 불변의 스토리지 이력이 있으므로 이 단계가 필요하지 않으며, 대신 다른 프리미티브인 브랜치로 대체됩니다.

기존 복구가 새 인스턴스를 프로비저닝하고 데이터를 복사하는 반면, Lakebase에서의 복구는 이력의 특정 시점에 있는 브랜치입니다. 이 새로운 브랜치는 자체적인 독립 컴퓨팅과 자체 연결 문자열을 가지며, 프로덕션과 완전히 독립적으로 쿼리할 수 있습니다. 원래 인스턴스의 복제본은 아니지만 마치 복제본처럼 느껴집니다.

복구에 이 프리미티브를 사용하는 방법은 다음과 같습니다.

  • 메인 브랜치에서 오류가 발생하면 과거의 타임스탬프를 선택합니다(실제로 복구를 커밋하기 전에 쿼리를 실행하는 등의 방법으로 해당 타임스탬프를 검사할 수 있습니다).
  • 유효성을 검증하면 제어 평면(control plane)이 해당 타임스탬프를 스토리지 이력의 정확한 지점(올바른 LSN)에 매핑하고, 해당 브랜치를 생성한 다음 컴퓨팅을 연결합니다.
  • "복구된 데이터베이스"는 기본 데이터베이스에 저장된 데이터의 양과 관계없이 "배포(deploy)"를 누르는 즉시 바로 사용할 수 있는 새로운 브랜치입니다.

이것이 가장 중요한 개념이므로 다시 한번 강조해 보겠습니다.

브랜치는 데이터베이스를 복사하지 않습니다

이 복구 방식은 데이터 복사 과정을 완전히 없앱니다. 복구된 브랜치는 데이터를 복사할 필요가 없으며, 해당 시점까지 이미 존재하는 이미지 및 델타 레이어를 가리키기만 합니다.

  • 복사 및 재실행(copy-and-replay) 시스템에서 복구는 데이터 이동 작업입니다. 복사와 WAL 재실행이 완료될 때까지 데이터베이스는 실제로 존재하지 않습니다.
  • Lakebase에서는 "데이터베이스"가 이미 존재합니다. 복구는 메타데이터 작업으로, 과거의 특정 시점을 가리키는 포인터에 불과합니다. 남은 일은 자체 컴퓨팅 리소스를 사용하여 해당 시점을 브랜치로 노출하는 것뿐입니다.

결과: 100 TB 복구도 10 GB 복구만큼 빠릅니다

이로써 규모 확장이 운영 측면에서 더 이상 두렵지 않다는 이점이 있습니다. 복구가 메타데이터 작업이라면, 소요 시간은 데이터 크기에 따라 늘어나지 않으며 작동 메커니즘도 동일하게 유지됩니다.

image1.png

데이터베이스의 크기에 관계없이:

  • 주소 지정이 가능한 과거 상태에 도달하는 것이 거의 즉각적입니다.
  • 해당 상태를 검증하는 데는 검사 및 읽기로 선택한 데이터를 처리하는 만큼의 시간만 소요됩니다.

사람이나 에이전트는 거대한 Postgres 데이터베이스에서도 장애 발생 후 쿼리 가능한 과거 상태에 언제든지 즉시 도달할 수 있습니다.

에이전트는 복구 기능을 기반으로 구축할 수 있습니다

image2.png

Lakebase에서의 복구는 타임스탬프에 브랜치를 생성하는 간단한 작업입니다. 이 루프는 매우 짧아서 에이전트가 장애 해결뿐만 아니라 일반적인 도구 호출처럼 처리할 수 있습니다.

이것이 바로 Replit이나 v0와 같은 에이전트 플랫폼이 버전 관리나 실행 취소(undo) 기능을 구축하기 위해 실제로 제품화하는 부분입니다. 일반적인 루프는 다음과 같습니다.

  1. 에이전트가 앱을 변경하면 데이터베이스가 변경됩니다.
  2. 플랫폼은 메인의 스냅샷으로 체크포인트를 저장합니다. 그리고 코드 버전 옆에 체크포인트 ID를 저장합니다.
  3. 사용자가 실행 취소를 누르거나 UI에서 이전 버전을 선택합니다.
  4. 플랫폼은 해당 체크포인트를 찾아 라이브 브랜치에 복구합니다.
  5. 스키마와 데이터가 "이전 코드"와 일치하는 데이터베이스 버전으로 즉시 되돌아갑니다.

기존의 PITR은 너무 느리고 무거워서 실시간 워크플로우를 지원하기 어렵지만, 타임스탬프 기준의 브랜치는 제품의 일부로 포함될 만큼 충분히 빠르고 저렴합니다.

Lakebase의 아키텍처는 복구의 모습을 바꿉니다

기존의 복구는 데이터베이스가 커질수록 더 느려지고 무거워집니다. 하지만 브랜치 기반 복구는 그렇지 않습니다. 이력(History)은 이미 컴퓨팅 외부에서 유지되므로, 과거의 특정 시점은 다시 구축해야 하는 대상이 아니라 브랜치로 열 수 있는 대상입니다. 10 GB이든 100 TB이든 관계없이 복구 과정은 동일합니다. 타임스탬프를 선택하고, 브랜치를 생성한 다음, 컴퓨팅을 연결하기만 하면 됩니다. 대규모 장애도 더 이상 두렵지 않습니다.

직접 경험해 보세요: Lakebase Postgres 데이터베이스를 생성하고, 상당한 양의 데이터를 로드한 다음, 복구를 실행해 보세요. 지금까지 이 기능 없이 어떻게 지내왔는지 놀라게 될 것입니다.

(이 글은 AI의 도움을 받아 번역되었습니다. 원문이 궁금하시다면 여기를 클릭해 주세요)

최신 게시물을 이메일로 받아보세요

블로그를 구독하고 최신 게시물을 이메일로 받아보세요.