메뉴
HN
Hacker News 28일 전

Postgres와 S3 Parquet를 연결하는 LTAP 아키텍처 해설

IMP
8/10
핵심 요약

전통적인 데이터베이스의 단일 병목 문제를 해결하기 위해 스토리지와 컴퓨팅을 외부 클라우드 서비스로 분리한 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 논문을 읽어보시기 바랍니다. 컴퓨터 과학 역사상 가장 복잡한 논문 중 하나라는 점을 미리 경고해 둡니다.)

사실상 이 설계가 현재 모든 데이터베이스의 근간이 되었지만, 모놀리식 아키텍처는 동시에 다음과 같은 수많은 과제를 야기합니다.

원문 보기
원문 보기 (영어)
Skip to main content Summary Almost every traditional database keeps its write-ahead log and data files on one machine's disk, which is the root cause of data loss risk, expensive read replicas and high-availability clones, and analytics queries that drag down transactions. Lakebase makes Postgres compute stateless by externalizing the log and data files into independent cloud services (SafeKeeper and PageServer), unlocking unlimited storage, elastic compute, durable writes, simpler HA, and instant branching, all with no meaningful added latency. LTAP goes further by storing operational data once in open columnar formats that both Postgres and Lakehouse engines read, so analytics runs on the same fresh data transactions just wrote, with no CDC pipeline, no second copy, and no slowdown to the transactional workload. Unlike HTAP, which tries to unify both workloads in one engine, LTAP unifies at the storage layer and keeps the best engine for each job. When I started my PhD at UC Berkeley 16 years ago, my advisor told me: "OLTP databases are a solved problem. They work. Focus on analytics." We were at the early innings of being able to collect far more data, structured and unstructured, and apply machine learning (which we now call “AI”). So I took the advice and joined my cofounders on the research project that became Apache Spark, and later on we started Databricks. As we built Databricks, we started using various databases out there, and we realized OLTP databases were far from a solved problem: they were clunky, difficult to scale, and incredibly fragile. We were frustrated enough at some point that we asked ourselves what an OLTP database would look like if we were to design it today. That question led to Lakebase , our serverless Postgres database. This post takes a deep dive into the Lakebase OLTP architecture. We start at the storage layer of a traditional monolithic database to see where the pain comes from, then we look at how Lakebase rearranges those same pieces into independent, externalized services. Finally, we turn to LTAP , where that same architecture lets transactions and analytics run on a single copy of the data, in real time, without the delays and extra cost of CDC or "mirroring.” The database as a monolith The vast majority of databases running in the world today are monoliths. This includes MySQL, Postgres, classic Oracle. Lakebase is built on Postgres (as it happens, was also born at Berkeley ), so we will be using Postgres as the primary example here, but most databases work similarly: You provision one machine that runs the database engine and the storage. In these database systems, there are two things on disk that matter the most: the write ahead log (WAL) and the data files . When you commit a transaction, the database does not immediately go and rewrite the data files. That would be slow, because the rows you are touching are scattered across the file in places that require random I/O. Instead, the database first appends a description of the change to the WAL, which is a sequential log on disk. A transaction is considered committed the moment that log entry is durably written. Only later, asynchronously, does the database go back and update the actual data files to reflect the change. One simple way to think about this: the WAL exists to make writes fast (and safe), and the data files exist to make reads fast. The log lets you commit a transaction with a single sequential append instead of a scattering of random I/O. The data files let you answer a query by reading the current state directly, instead of replaying the entire history of the database from the beginning of time. (If you want to understand all the intricate details of this design, read the 69-page long ARIES paper . Be warned that this is one of the most complex papers in computer science.) As this design has become the foundation for virtually all databases out there, the monolithic architecture also creates a lot of challenges: Data loss from misconfiguration. A commit is only as durable as the disk flush behind it. If the database, the operating system, or the storage layer is configured such that a write to the WAL is acknowledged to the client before it has actually been flushed to durable media, then a commit can vanish in a power loss or kernel panic. These settings are subtle, easy to get wrong, and the failure is often silent. The operating system might even decide to lie to you about flushing ! Data loss from node loss. Even with flushes configured correctly, the WAL and the data files live on one machine. If that machine's disk dies, the data on it dies too. Note that network attached storage or redundancy techniques like RAID-1/RAID-10 can improve durability but do not fundamentally solve this issue. If the storage mount dies, so does your data access. Scaling reads requires a physical clone. When one box can no longer serve your traffic, the standard answer is to add a read replica. But a read replica is a full physical copy of the entire database, streaming the WAL from the primary and replaying it. Provisioning one means copying the whole dataset and then catching up on the log. For a large database, that is not a quick operation and might even bring down the database. High availability also requires a physical clone. Surviving the loss of the primary means running at least one additional standby node, which is itself a complete physical copy of the database kept in sync from the WAL. You pay for at least twice the infrastructure, you wait a long time to bring a standby online, and you have to set up synchronous replication to avoid losing any data when the primary goes down. (In practice, many recommend 3 or more nodes.) Analytics contend with your transactional traffic. A heavy analytical query runs against the same hardware resources as your latency-sensitive transactional workload. One large reporting query or one GDPR cleanup can degrade your main OLTP queries. You can run the analytical queries in a separate replica, but you end up paying for the replica and still don’t get optimal performance due to the row oriented nature of OLTP storage (analytics requires column-oriented storage for high performance). Almost every one of these problems traces back to the same root cause from the monolithic architecture: the WAL and the data files are stored inside a single machine. Durability is tied to that machine's disk. Scaling and availability require physically cloning that machine. Workloads interfere because they share that machine. Lakebase architecture If you were to redesign an OLTP database today, you’d start with the components of the modern cloud: cheap and highly durable cloud object storage paired with elastic compute. This is the path the Neon team took on and the foundation of what became Lakebase. The core move is to make the Postgres compute instances stateless . We do this by externalizing the WAL and the data files on local disks into purpose-built, independently scalable services. The compute layer becomes a stateless Postgres engine that can be started, stopped, and replicated freely, because it no longer owns the data. Let’s see how these two storage services can work together to solve the aforementioned challenges without sacrificing performance. Scaling writes: WAL becomes SafeKeeper In a monolith, a write is made durable by flushing it to the local disk. In a Lakebase, the WAL is externalized to a distributed storage service called the SafeKeeper . Instead of relying on disk flush for durability, a commit is made durable by replicating the log record across a quorum of SafeKeeper nodes using Paxos-based network replication. There is no longer a disk whose failure loses your data, and there is no longer a misconfigured flush quietly undermining your durability guarantee. It’s natural to ask at this point: does moving commits from WAL on local disk to WAL on SafeKeeper increase the write latency due to the ex