Postgres와 S3 Parquet를 연결하는 LTAP 아키텍처 해설
전통적인 데이터베이스의 단일 병목 문제를 해결하기 위해 스토리지와 컴퓨팅을 외부 클라우드 서비스로 분리한 Lakebase의 OLTP 아키텍처를 심층 분석합니다. 이를 통해 단일 데이터 복사본과 개방형 컬럼 형식을 활용해 별도의 데이터 파이프라인(CDC)이나 부하 없이 OLTP와 분석 쿼리를 동시에 처리하는 LTAP의 혁신성을 설명합니다.
요약 거의 모든 전통적인 데이터베이스는 쓰기 로그(WAL)와 데이터 파일을 단일 머신의 디스크에 저장합니다. 이로 인해 데이터 유실 위험, 비용이 많이 드는 읽기 복제본(read replica) 및 고가용성(HA) 클론 구성, 그리고 트랜잭션 성능을 저하시키는 분석 쿼리 등의 문제가 발생합니다. Lakebase는 로그와 데이터 파일을 독립적인 클라우드 서비스(SafeKeeper와 PageServer)로 외부화하여 Postgres의 컴퓨팅을 무상태(stateless)로 만듭니다. 이를 통해 무제한 스토리지, 탄력적인 컴퓨팅, 내구성 있는 쓰기, 단순화된 고가용성, 즉각적인 브랜칭(branching)을 실현하며, 이 모든 것을 유의미한 지연 시간(latency) 추가 없이 제공합니다.
LTAP(Lakehouse Transactional and Analytical Processing)는 이러한 개념을 더욱 발전시켜, 운영 데이터를 단 한 번만 개방형 컬럼 형식(open columnar format)으로 저장한 뒤 Postgres와 레이크하우스 엔진이 모두 읽을 수 있게 합니다. 따라서 데이터 변경 감지(CDC) 파이프라인이나 두 번째 데이터 복사본 없이, 트랜잭션 워크로드를 느리게 하지 않으면서도 방금 기록된 최신 데이터를 바탕으로 즉각적으로 분석을 실행할 수 있습니다. 두 가지 워크로드를 단일 엔진으로 통합하려는 HTAP와 달리, LTAP는 스토리지 계층에서 데이터를 통합하고 각 작업에 가장 적합한 엔진을 유지합니다.
16년 전 제가 UC 버클리에서 박사 과정을 시작했을 때, 지도교수님은 이렇게 말씀하셨습니다. "OLTP 데이터베이스는 이미 해결된 문제이다. 잘 작동하니, 분석에 집중해라." 당시 우리는 구조화 및 비구조화된 대규모 데이터를 수집하고 (지금 우리가 'AI'라고 부르는) 머신러닝을 적용할 수 있는 초창기에 있었습니다. 저는 그 조언을 받아들여 훗날 아파치 스파크(Apache Spark)가 된 연구 프로젝트에 공동 창립자들과 합류했고, 이후 다브릭스(Databricks)를 설립했습니다.
다브릭스를 키워나가면서 우리는 다양한 데이터베이스를 사용하기 시작했고, OLTP 데이터베이스가 결코 해결된 문제가 아니라는 것을 깨달았습니다. 그것들은 다루기 어렵고, 확장하기 힘들며, 믿을 수 없을 정도로 취약했습니다. 우리는 어느 시점에서 너무나도 좌절한 나머지, 오늘날 우리가 직접 OLTP 데이터베이스를 설계한다면 어떤 모습일지 자문했습니다. 이러한 질문에서 출발한 것이 서버리스 Postgres 데이터베이스인 'Lakebase'입니다.
이 글에서는 Lakebase의 OLTP 아키텍처에 대해 깊이 있게 살펴봅니다. 먼저 전통적인 모놀리식(monolithic) 데이터베이스의 스토리지 계층에서 출발해 문제의 원인이 무엇인지 확인한 다음, Lakebase가 이 동일한 구성 요소들을 어떻게 독립적이고 외부화된 서비스로 재배열하는지 알아보겠습니다. 마지막으로, 이 아키텍처가 어떻게 CDC나 데이터 '미러링'으로 인한 지연과 추가 비용 없이 단일 데이터 복사본에서 실시간으로 트랜잭션과 분석을 동시에 실행할 수 있게 하는지 살펴보겠습니다.
모놀리식 데이터베이스 오늘날 작동하는 대부분의 데이터베이스는 모놀리식 구조입니다. 여기에는 MySQL, Postgres, 오라클 클래식 등이 포함됩니다. (우연히도 Postgres 역시 버클리에서 탄생했습니다.) Lakebase는 Postgres를 기반으로 구축되었으므로 여기서는 Postgres를 주요 예시로 사용하지만, 대부분의 데이터베이스가 유사한 방식으로 작동합니다. 데이터베이스 엔진과 스토리지를 실행하기 위해 단일 머신을 프로비저닝하는 것입니다.
이러한 데이터베이스 시스템의 디스크에는 가장 중요한 두 가지가 있습니다. 바로 WAL(Write-Ahead Log, 사전 쓰기 로그)와 데이터 파일(Data files)입니다. 트랜잭션을 커밋할 때 데이터베이스는 즉각적으로 데이터 파일을 다시 쓰지 않습니다. 만약 그렇게 한다면 느릴 것입니다. 왜냐하면 작업 중인 행(row)들이 임의의 입출력(random I/O)이 필요한 파일 내 여러 곳에 흩어져 있기 때문입니다. 대신 데이터베이스는 먼저 변경 사항에 대한 설명을 디스크의 순차적인 로그인 WAL에 추가(append)합니다. 해당 로그 항목이 내구성 있게 기록되는 순간 트랜잭션은 커밋된 것으로 간주됩니다. 데이터베이스가 실제 데이터 파일로 돌아가 변경 사항을 반영하여 업데이트하는 것은 그보다 나중에 비동기적으로 이루어집니다.
이를 간단히 요약하자면 이렇습니다. WAL은 쓰기 작업을 빠르고 안전하게 만들기 위해 존재하고, 데이터 파일은 읽기 작업을 빠르게 만들기 위해 존재합니다. 로그는 흩어진 임의의 입출력 대신 단일 순차적 추가 만으로 트랜잭션을 커밋할 수 있게 해줍니다. 데이터 파일은 시간의 처음부터 데이터베이스의 전체 기록을 다시 재생하는 대신 현재 상태를 직접 읽음으로써 쿼리에 대한 응답을 가능하게 합니다. (이 설계의 복잡한 모든 세부 사항을 이해하고 싶다면 69페이지 분량의 ARIES 논문을 읽어보시기 바랍니다. 컴퓨터 과학 역사상 가장 복잡한 논문 중 하나라는 점을 미리 경고해 둡니다.)
사실상 이 설계가 현재 모든 데이터베이스의 근간이 되었지만, 모놀리식 아키텍처는 동시에 다음과 같은 수많은 과제를 야기합니다.