LakeBase ابداع نکرد. فقط fsync رو جابه‌جا کرد.

databases postgres architecture mechanism cloud

Databricks رو ۲۲ ژانویه ۲۰۲۶ LakeBase Postgres رو ship کرد: Postgres ی واقعی، wire-compatible، با driver های استاندارد، ORM ها، psql، و pgvector و PostGIS همراه. رو AWS از ژانویه general available بود، Azure تو مارس GA شد، و adoption ش گزارشاً با دو برابر سرعت محصول warehousing شون رشد می‌کنه. یه reimplementation نیست؛ query engine همون Postgres ی دست‌نخورده‌ست. چیزی که عوض شده، چیزیه که زیر commit هست. یه transaction دیگه وقتی durable نمی‌شه که یه SSD ی local فلش کنه. وقتی durable می‌شه که یه quorum از storage node ها موافق باشن که اتفاق افتاده. headline مارکتینگ database branching ـه، «Git برای database ت». headline side effect ـه.

LakeBase چیه

product facts، کوتاه. Databricks Neon رو مه ۲۰۲۵ خرید؛ LakeBase نتیجه‌ی product شدنشه. Serverless Postgres با scale-to-zero، امروز Postgres 18 با pgvector، از جولای ۲۰۲۶ SLA، SOC 2 Type 2، PCI-DSS و HITRUST این ماه اومدن، storage quota ی default ی ۳۲ TB، و Lakehouse Sync که داده‌ی operational رو بدون pipeline می‌ریزه تو Delta table ها. PostGIS، extension ها، همون tooling ی که الان استفاده می‌کنی. هیچ‌کدوم‌شون قسمت جالب ماجرا نیستن.

Mechanism

architecture رو Postgres رو به دو تا layer تقسیم می‌کنه که با یه WAL stream به هم وصلن.

Compute یه stateless Postgres ـه. Parse می‌کنه، plan می‌کنه، اجرا می‌کنه، و فقط transient state داره: shared buffer ها تو RAM به‌علاوه یه local NVMe cache. هیچ data ی durable ی رو صاحب نیست. به‌خاطر همینه که می‌تونه restart، autoscale، یا scale-to-zero بشه بدون recovery story؛ چیزایی روش نیست که بخواد recover بشه.

WAL از روی machine بیرون کشیده می‌شه تو یه گروه safekeeper. یه transaction وقتی commit می‌شه که یه quorum به وسیله‌ی Paxos consensus یه log record رو acknowledge کنه، نه وقتی که یه local fsync برگرده. این جمله‌ایه که همه‌چیز دیگه ازش درمیاد: commit یه event ی distributed-systems ـه.

Pageserver ها data file ها رو نگه می‌دارن، rebuild شده از WAL. Page version ها رو on-demand تو یه LSN ی requested materialize می‌کنن، و مثل یه write-through cache بالای object storage کار می‌کنن. Object storage (رو AWS یعنی S3) page history ی immutable رو نگه می‌داره و خارج از hot read path ـه؛ فقط pageserver ها ازش می‌خونن. read path اینه: buffer pool، local NVMe، pageserver، object storage، و تو اولین cache hit می‌ایسته.

شما latency ی fsync ی یه SSD ی local رو با latency ی consensus ی یه log ی replicated عوض کردید. Databricks بحث می‌کنه که برای هرکی که sync replication داره این یه جور معاوضه‌ی خنثیه: یه network round trip جای اون یکی رو می‌گیره، نه اینکه اضافه بشه. منصفانه‌ست، ولی دقت کن چی عوض شده. durability ی commit ت الان به سلامت یه quorum ی distributed وابسته‌ست، و موقع partition سیستم باید بین block کردن write ها و ریسک یه durability gap انتخاب کنه. monolith هیچ‌وقت مجبور به این انتخاب نبود.

چرا branching و scale-to-zero consequence هستن، نه feature

اینجا قسمتیه که ارزش internalise کردن داره. چهار تا bulletpoint رو landing page ی LakeBase در واقع یه تصمیم architectural ـه با چهار تا کلاه.

یه branch یه metadata operation ـه که به یه LSN اشاره می‌کنه. هیچ data ای کپی نمی‌شه. یه database ی ۱۰ گیگی و یه database ی ۲ ترابایتی رو همون تعداد ثانیه branch می‌شن، و فقط برای page هایی که branch تغییر می‌ده پول می‌دی؛ اگه ۱ گیگ از یه database ی ۱۰۰ گیگی رو تغییر بدی، branch حدود ۱ گیگ اضافه درمیاد.

scale-to-zero همون جمله‌ست از سمتی دیگه خونده شده. Compute هیچ‌چیز durable ای نداره، پس می‌تونه بخوابه. point-in-time recovery یعنی compute به یه LSN ی گذشته وصل بشه، نه اینکه data restore بشه. read replica یه compute ی دومه که به storage ی موجود وصل می‌شه، بدون data movement. چهار تا feature، یه دلیل.

Ledger ی tradeoff ها

externalized durability یه معامله‌ست، و ledger دو تا ستون داره.

PropertyPostgres ی monolithicLakeBase
Commit acklocal fsyncquorum consensus از روی network
سرد خوندن pagebase image روی دیسکreplay کردن WAL delta ها تا LSN
Database branchpg_dump، از چند دقیقه تا چند ساعتmetadata operation، چند ثانیه
Compute ی بی‌کار۲۴/۷ cost دارهصفر
Superuser، tablespaces، logical replicationهستنیست

row ی cold page احترام می‌خواد. resolve کردن version ی فعلی یه page می‌تونه یعنی replay کردن یه chain بلند از WAL delta ها روی یه base image، و اگه compaction و image generation بد tune شده باشن، یه tail latency می‌گیری که تو demo پیدا نیست و ساعت ۲ نصفه‌شب پیدا می‌شه. engineering ی خود Databricks تأیید می‌کنه که این واقعی بوده: Full Page Writes رو خاموش کردن و image generation رو بردن تو pageserver، و ۹۴٪ کاهش WAL traffic و تا ۵× write throughput گزارش کردن. آدم این‌قدر engineering رو خرج یه مشکلی نمی‌کنه که وجود نداره.

بقیه‌ی ledger، از تحلیل‌های third-party. branching یه merge semantic نداره: branch یه snapshot تو یه LSN ـه و هیچ‌وقت با parent ش sync نمی‌شه، پس mental model ی Git دقیقاً همون‌جایی می‌شکنه که Git مفیدترینه، موقع merge. branch های long-lived یه page history رو pin می‌کنن و storage رو بی‌صدا گرون می‌کنن؛ immutable storage نوشتن‌ش ارزونه و فراموش‌کردنش گرون. connection ها یه جوری ephemeral هستن که session state رو سورپرایز می‌کنن: idle timeout ی ۲۴ ساعته، maximum lifetime ی ۳ روزه، cold resume ی حدود ۵۰۰ میلی‌ثانیه، و advisory lock ها و temp table ها و prepared statement ها با connection می‌میرن. HA config نمی‌تونه scale-to-zero بشه، پس compute ی production ۲۴/۷ cost داره. و governance هم aligned ـه، نه merged: Unity Catalog سمت lakehouse رو govern می‌کنه و Postgres role ها direct connection ها رو؛ دو تا مسیر authorization که باید consistent نگه‌شون کنی.

هیچ‌کدوم‌شون fatal نیستن. همه‌شون قیمتن.

کجا generalize می‌شه

test ی قابل انتقال: وقتی یه database vendor یه لیست feature می‌ده، feature ها رو بر اساس تصمیم architectural ی که imply شون می‌کنه گروه‌بندی کن، بعد اون تصمیم رو price کن، نه لیست رو.

لیست ی LakeBase، branching، scale-to-zero، PITR، replica ی فوری، sync table ها به Delta، یه storage foundation برای OLTP و analytics، همه از جمله‌ی «durability تو یه distributed log روی object storage زندگی می‌کنه» درمیاد. cost ها، consensus تو commit path، مدیریت cold page ی tail ها، discipline ی GC، ephemeral بودن session ها، از همون جمله درمیاد. نمی‌تونی feature ها رو بگیری و cost ها رو رد کنی؛ همون یه تصمیمه.

این برای هر externalized-durability system ی که از این به بعد evaluate می‌کنی صادقه: storage layer ی جدا‌شده‌ی Aurora، خود Neon، هر disaggregated OLTP engine ی که تو roadmap ها میاد. هرکدوم همون معامله رو با یه wrapper ی متفاوت می‌ذارن رو میز، و evaluation همیشه همین دو تا سواله: کدوم feature ها consequence ی تصمیم storage هستن؟ تصمیم storage ساعت ۲ نصفه‌شب چیزی می‌بره که تو demo نمی‌بره؟

اون trap

trap اینه که لیست feature رو بخونی product. branching product نیست. یه WAL ی quorum-committed روی object storage ـه product ـه، و branching یکی از کارایی‌های این architecture ـه که monolith نمی‌تونه بکنه.

trap ی دومی فاصله‌ی demo تا production ـه. عددهای pgbench که vendor گزارش کرده، حدود ۱۷۳۱ TPS برای LakeBase در مقابل حدود ۱۵۰۸ برای Aurora PostgreSQL رو یه workload ی ۴ میلیونی ردیف، عددهای steady-state هستن. تو steady state ـه که architecture های disaggregated بهترین شکلشون رو نشون می‌دن؛ تو tail هاست که ledger زندگی می‌کنه. cold page ی replay latency، رفتار quorum موقع partition، فشار GC از یه branch ی فراموش‌شده: هیچ‌کدوم تو یه demo ی ۹۰ ثانیه‌ای پیدا نمی‌شن، همه‌شون تو یه صفحه پیدا می‌شن.

قانون پایانی. وقتی durability یه event ی distributed-systems می‌شه، هر consequence ی اون تصمیم، از هر دو طرف ledger، تا وقتی ندونی از کدوم جمله دراومده، شبیه یه feature به نظر میاد. جمله‌ی LakeBase اینه: «commit تو یه quorum روی object storage زندگی می‌کنه.» جمله رو بخون، بعد bulletpoint ها دیگه مارکتینگ نیستن، arithmetic هستن.

$ cat GIT .md
· 7 دقیقه مطالعه

۸۴ تا repository ناپدید شدن. راه‌حل mkdir بود.

S3 چیزی به اسم directory خالی نداره، و تو یه git repository ی کاملاً packed شده، directory های refs دقیقاً همون‌ان: خالی. یه sync ی فایل‌به‌فایل همه‌ی object ها رو سالم منتقل کرد ولی دو تا directory یی که git لازم داره تا به چیزی بگه repository رو drop کرد، پس از ۵۱۷ تا، ۸۴ تا به شکل خوانا‌نشدنی برگشتن در حالی که database هنوز می‌گفت commit دارن. health check های migration هم کل مدت سبز موندن، چون هیچ‌کدوم هیچ‌وقت یه repository رو باز نمی‌کنن.

git aws s3 gitlab mechanism
$ cat KUBERNETES .md
· 8 دقیقه مطالعه

constraint ارضا شده بود. با این حال zone خالی بود.

یه topologySpreadConstraint هیچ‌وقت چیزی بیشتر از یه statement درباره‌ی جمعیتی نیست که selector ش match می‌کنه، و یه label ای که operator ست کرده می‌تونه بی‌صدا sibling Deployment ها رو بریزه توی یه شمارش مشترک. سه تا collector تک‌تک zone spread ی hard خودشون رو ارضا کردن، در حالی که union شون یه zone رو خالی گذاشته بود، و repair ی استاندارد هر دفعه روی همون جواب غلط converge می‌کرد.

kubernetes scheduling opentelemetry finops mechanism
$ cat CLICKHOUSE .md
· 9 دقیقه مطالعه

۱۳۶ میلیون PUT برای ۱۷ GiB داده

object storage به ازای هر operation پول می‌گیره، و یه part ی ClickHouse روی disk ی S3 یه object نیست، به ازای هر column یه object ـه. پس هزینه‌ی یه cold tier تابع اینه که چند تا part وجود داره، نه اینکه چند byte توشونه، و هر setting ای که merge ها رو گرسنه بذاره می‌شه یه خط روی صورت‌حساب. دو تا default ی chart دقیقاً همین کارو کردن، و fix ی که جلوش رو گرفت هیچ‌وقت commit نشده بود.

clickhouse s3 finops observability mechanism