پستگرس Neon چطور هر ۸۱ ثانیه سایزش رو عوض میکنه
خلاصهٔ کاملتر
انتخاب سایز اینستنس دیتابیس قبل از دیدن ورکلود، یه عادت قدیمی و پرهزینهست. Lakebase Postgres، دیتابیس Neon، این مرحله رو کلاً حذف کرده؛ به گفتهٔ خودشون یه دیتابیس پروداکشن معمولی ماهی ۳۲٬۰۱۶ بار سایز کامپیوتش عوض میشه، یعنی تقریباً هر ۸۱ ثانیه یهبار. چیزی که این کارو ممکن کرده جدا بودن لایههاست: کامپیوت فقط کوئری اجرا میکنه و هیچ استیت پایداری نداره، لایهٔ استوریج مسئول دوامه. پس نود کامپیوت میتونه بالا بیاد، جابهجا شه یا سایزش عوض شه بدون اینکه دیتابیس زیرش تکون بخوره.
لایهٔ استوریج خودش سه تیکهست: safekeeperها WAL رو روی SSD رپلیکیت میکنن، pageserverها نسخههای صفحه رو بازسازی میکنن و آبجکتاستوریج رکورد بلندمدت رو نگه میداره. سؤال بعدی اینه که کِی باید سایز عوض شه. الگوریتم سه سیگنال رو میپاد که هرکدوم سایز هدف خودش رو میده: cpuGoalCU، memGoalCU و lfcGoalCU. هدف نهایی بزرگترینِ این سهتاست، محدود به کف و سقفی که کاربر تنظیم کرده. سمت CPU سادهست: هر ۵ ثانیه میانگین بار یکدقیقهای خونده میشه تا بار زیر ۹۰٪ ظرفیت بمونه.
حافظه مدل شکست متفاوتی داره: کمبود CPU فقط کوئری رو کند میکنه، ولی اگه پستگرس بیشتر از رم موجود بگیره، کرنل میتونه پروسهها رو بکشه. برای همین حافظه تو دو فرکانس دیده میشه؛ هر ۵ ثانیه متریک کلی VM و هر ۱۰۰ میلیثانیه مصرف خود پستگرس توسط vm-monitor. هدف اینه که مصرف زیر ۷۵٪ رم تخصیصیافته بمونه. همین vm-monitor هر پیشنهاد کوچکشدن رو وتو میکنه اگه جا برای پروسههای در حال اجرا نمونه. این طراحی جای نسخهٔ قدیمیتر مبتنی بر رویداد memory.high در cgroup رو گرفت.
سیگنال سوم جواب یه نقطهکور مهمه. تو معماری جداشده، صفحهای که محلی نیست از pageserver گرفته و بعد کش میشه؛ این کش، که اولش اسمش Local File Cache یا LFC بود، یه کش دیسکیه که مثل ادامهٔ قابلتغییرسایزِ shared buffers کار میکنه. تو خیلی از ورکلودهای OLTP، کارایی درست همونجا جهش میکنه که working set تو حافظهٔ محلی جا بشه. اما cache miss یعنی کوئری منتظر شبکه میمونه و مصرف CPU پایین میآد؛ پس دقیقاً همون لحظهای که کش بزرگتر جواب میداد، سیگنال CPU فشاری نمیبینه.
برای همین working set رو مستقیم تخمین میزنن. ابزار کلاسیکش HyperLogLog هست، ولی HLL استاندارد فقط رشد میکنه و نمیدونه هر رجیستر کِی آخرینبار دیده شده؛ یعنی یه ایمپورت قدیمی تا ابد تو تخمین میمونه و کامپیوت رو بیخود بزرگ نگه میداره. راهحل Neon اینه که بهجای ستکردن یه بیت، تایماستمپ لحظه رو تو اون خونه مینویسن؛ برای تخمین از زمان T به بعد، هر خونهای که بعد از T آپدیت شده ست حساب میشه. خروجی، تخمین برای پنجرههای ۱ تا ۶۰ دقیقهایه که هر ۲۰ ثانیه جمع میشه.
انتخاب پنجره با دنبالکردن جهش تخمین انجام میشه: جستوجو از دقیقهٔ پنجم شروع میشه و اگه جهش تیزی پیدا نشه، تخمین ۶۰ دقیقهای ملاکه. بخش دوم، اعمال سایز روی VM زندهست. هر اینستنس پستگرس داخل VM خودش تو یه کلاستر Kubernetes میچرخه و چهار جزء کار رو جلو میبرن: اتواسکیلر-ایجنت روی هر نود، vm-monitor داخل هر VM، یه اسکجولر Kubernetes اصلاحشده که باید هر بزرگشدن رو تأیید کنه، و NeonVM روی QEMU و KVM که تغییر رو اعمال میکنه. اگه نود جا نداشته باشه، VM لایو مایگریت میشه و چون IP حفظ میشه کانکشنها قطع نمیشن.
نکات کلیدی:
- به گزارش Neon، یه دیتابیس پروداکشن معمولی ماهی ۳۲٬۰۱۶ بار سایز کامپیوتش عوض میشه (هر ۸۱ ثانیه یهبار).
- سایز هدف = بزرگترینِ cpuGoalCU، memGoalCU و lfcGoalCU، محدود به کف و سقف تنظیمشدهٔ کاربر.
- آستانهها: بار CPU زیر ۹۰٪ ظرفیت، مصرف حافظه زیر ۷۵٪ رم تخصیصیافته.
- سه بازهٔ حلقه: ۱۰۰ میلیثانیه (حافظهٔ پستگرس)، ۵ ثانیه (CPU و حافظهٔ کلی)، ۲۰ ثانیه (تخمین working set).
- HyperLogLog زماندار: بهجای بیت، تایماستمپ ذخیره میشه تا تخمین برای پنجرههای ۱ تا ۶۰ دقیقهای دربیاد.
- الگوریتم رشد working set رو به جلو هم پیشبینی میکنه، ولی فقط تا بازهٔ کنترل بعدی تا کامپیوت نوسان نکنه.
- کوچکشدن بهاندازهٔ بزرگشدن جدی گرفته شده؛ vm-monitor هر downscale ناامن رو رد میکنه.
- Lakebase Postgres هم روی Neon و هم روی Databricks با همون هستهٔ مشترک اجرا میشه.




