cloudflare چگونه خوشه‌های توزیع‌شدهٔ postgresql را اداره می‌کند؟

Cloudflare چگونه خوشه‌های توزیع‌شدهٔ PostgreSQL را اداره می‌کند؟

دادهٔ رابطه‌ای در اِج (Relational Data at the Edge)

نکات کلیدی

  • ذخیره‌سازی و دسترسی به داده در لبه (Edge) با کاهش تأخیر حساس به موقعیت، دستاوردهای بزرگ عملکردی ایجاد می‌کند.

  • ذخیره و مدیریت دادهٔ رابطه‌ای در لبه با مجموعه‌ای خاص از چالش‌ها همراه است؛ چالش‌هایی که از محدودیت‌های همیشگی CAP و شرایط بارِ بسیار متغیر ناشی می‌شوند و به مصالحه‌های دقیق نیاز دارند.

  • کلاودفلر یک معماری پایگاه‌دادهٔ بین‌ناحیه‌ای توزیع‌شده را اجرا می‌کند و PostgreSQL را در چند منطقه پخش می‌کند تا تاب‌آوری و غلبه بر خرابی‌های سریع فراهم شود.

  • تأخیر در تکثیر یک چالش مهم است. مخصوصاً برای سیستم‌های توزیع‌شدهٔ تکثیرشده، طراحی برای حالت‌های «تنزل‌یافته» خیلی سخت‌تر از طراحی برای حالت‌های «خرابی کامل» است.

  • تعبیه‌شدن در لبه و هم‌مکانیِ ذخیره‌سازی و محاسبه آیندهٔ دادهٔ رابطه‌ای است.

این متن چیست؟

این یک خلاصه از سخنرانی‌ای است که در QCon San Francisco در اکتبر ۲۰۲۳ ارائه دادیم؛ جایی که دربارهٔ راه‌اندازی دسترس‌پذیری بالا (High Availability) صحبت کردیم و مصالحه‌هایی را که کلاودفلر در هر بخش سیستم مجبور بوده انجام دهد بررسی کردیم. همچنین به چالش‌های عملکردی‌ای می‌پردازیم که کلاودفلر هنگام نزدیک‌تر کردن زیرساخت دیتابیس به لبه، بیش از هر زمان دیگری، با آن‌ها روبه‌رو شد و عمیقاً وارد راه‌حل‌هایی می‌شویم که پیاده‌سازی شده‌اند.

Edge چیست؟

لبه (Edge) در زمینهٔ سیستم‌های توزیع‌شده به سرویس‌هایی اشاره دارد که از نظر جغرافیایی نزدیکِ کلاینت‌ها قرار دارند. این شامل کارهایی مثل resolve کردن DNS، تحویل محتوا (content delivery)، و فایروالینگ IP می‌شود. به‌صورت سنتی، دیتاسنترهای متمرکز میزبان سرویس‌هایی مثل دیتابیس‌های رابطه‌ای بودند که از کلاینت‌ها دورتر بودند. نزدیکی به کلاینت معیار اصلی است؛ چون با سرویس‌دادن درخواست‌ها نزدیک‌تر به موقعیت کلاینت، هم تأخیر شبکه و هم هزینه‌ها کاهش پیدا می‌کند.

کنترل‌پلین (The Control Plane)

کلاودفلر از بیش از ۲۷ میلیون «دارایی اینترنتی» محافظت می‌کند و به‌طور میانگین ۴۶ میلیون درخواست HTTP در ثانیه را مدیریت می‌کند. شبکهٔ آن ۲۵۰ نقطه حضور (PoP) در سراسر جهان دارد و در شلوغ‌ترین کلاستر PostgreSQL، در پیک، بیش از ۵۵ میلیون عملیات روی ردیف در ثانیه را مدیریت می‌کند؛ با بیش از ۵۰ ترابایت داده در مجموع همهٔ کلاسترها.

کنترل‌پلین کلاودفلر تعداد زیادی میکروسرویس را هماهنگ می‌کند و داشبورد را تغذیه می‌کند. این لایه قوانین و تنظیمات سرویس‌های حیاتی شبکه در مسیر داده را مدیریت می‌کند. کلاسترهای دیتابیس برای هر مشتری داده‌هایی مثل تغییرات رکورد DNS، قوانین فایروال، مقابله با DDoS، مسیرهای API gateway، و اطلاعات سرویس‌های داخلی مثل مجوزهای صورتحساب و احراز هویت کاربر را ذخیره می‌کنند. تیم‌های اپلیکیشن اغلب از PostgreSQL برای اهداف خاص استفاده می‌کنند، از جمله استفاده از رویه ذخیره شده برای اجرای منطق کسب‌وکار با سازگاری تراکنشی.

PostgreSQL همچنین به‌عنوان یک صف outbox استفاده می‌شود؛ جایی که رویدادهای دامنه مثل قوانین DDoS تولیدشده از تحلیل ترافیک، در یک دیتاسنتر مرکزی ثبت می‌شوند.

یک daemon جداگانه این رویدادها را از دیتابیس برمی‌دارد و از طریق Kafka به سرویس‌های edge ارسال می‌کند؛ به این شکل سرویس‌های حساس به تأخیر می‌توانند بدون دسترسی مستقیم به دیتابیس کار کنند و همزمان از دوام فراهم‌شده توسط PostgreSQL و Kafka بهره ببرند.

کلاودفلر کل پشتهٔ نرم‌افزار و سرویس را روی bare metal اجرا می‌کند؛ یعنی با سرورهای رک‌مونت، کارت‌های شبکه با پهنای‌باند بالا، و نگهداری عملیاتی سروکار دارد. ذخیره‌سازی on-premise بیشترین انعطاف را می‌دهد و به تیم اجازه می‌دهد چیزهایی مثل تنظیم RAID مبتنی بر SSD را دقیق تیون کند و سیستم را با یک سیستم متن‌باز مدیریت کلاستر تقویت کند. چنین شفافیت و کنترل ریزدانه‌ای با دیتابیس‌های مدیریت‌شدهٔ ابری مثل Amazon RDS غیرممکن است.

البته این یعنی خبری از یک دکمهٔ جادویی مقیاس‌بندی خودکار برای افزایش فوری ظرفیت کلاستر هنگام افزایش بار نیست؛ یک چالش ذاتی در اجرای کامل پشته به‌صورت on-premise.

معماری

بیایید دربارهٔ معماری دیتابیس کلاودفلر در لبه صحبت کنیم که باید تراکنش‌هایی در حد میلیون‌ها در ثانیه را پردازش کند.

در طراحی سیستم، تیم «دسترس‌پذیری بالا» را در اولویت قرار داد و هدفش یک SLO با «پنج ۹» بود، با حداکثر پنج دقیقه و نیم downtime در سال برای کل پشته. بارهای تراکنشی عمدتاً read-heavy هستند. زیرساخت باید نرخ بالایی از خواندن و نوشتن را با حداقل تأخیر مدیریت کند و همزمان تحمل خطا را حفظ کند. کلاودفلر از شبکهٔ anycast مبتنی بر BGP به‌صورت داخلی استفاده می‌کند و کلاینت‌ها به‌طور طبیعی بین نمونه‌های پروکسی PgBouncer بالانس می‌شوند.

در حالی که BGP Anycast کوئری‌های خواندنی را با نزدیک‌کردن به کلاینت بهینه می‌کند، کوئری‌های نوشتن به ناحیهٔ primary که نمونهٔ اصلی دیتابیس در آن قرار دارد فوروارد می‌شوند.

cloudflare چگونه خوشه‌های توزیع‌شدهٔ postgresql را اداره می‌کند؟

شکل ۱: معماری دیتابیس کلاودفلر

در بالا، PgBouncer pool اتصال‌های سرور دیتابیس را برای کلاینت‌های اپلیکیشن مدیریت می‌کند. سپس HAProxy کوئری‌ها را بین چند نمونهٔ کلاستر دیتابیس load balance می‌کند تا از overload روی یک سرور جلوگیری شود. در یک راه‌اندازی معمول، یک نمونهٔ primary داده را به چند کپی تکثیر می‌کند تا نرخ بالایی از کوئری‌های خواندن پوشش داده شود؛ این کار توسط مدیر دسترس‌پذیری بالا یعنی stolon که پشتش etcd قرار دارد مدیریت می‌شود. در این تنظیم، etcd برای اجماع رهبری و سازگاری پیکربندی به‌صورت توزیع‌شده استفاده می‌شود.

مدل active-standby افزونگی داده بین مناطق را تضمین می‌کند؛ جایی که ناحیهٔ primary در پورتلند درخواست‌های ورودی را مدیریت می‌کند و ناحیهٔ standby در لوکزامبورگ آمادهٔ هدایت ترافیک یا غلبه بر خرابی است.

حالا هر لایه را بررسی می‌کنیم و اجزا و مصالحه‌ها را مرور می‌کنیم.

ماندگاری در لبه (Persistence at the Edge)

تصمیم برای ساخت یک دیتابیس edge که هم بسیار توزیع‌شده باشد و هم رابطه‌ای، باعث شد تیم به اصول بنیادی معماری فکر کند؛ مخصوصاً قضیهٔ CAP. چون اپلیکیشن از نظر جغرافیایی توزیع‌شده است و روی نرم‌افزار متن‌باز مثل PostgreSQL تکیه دارد، باید یا سازگاری را اولویت بدهید یا دسترس‌پذیری بالا را. معمولاً دومی انتخاب می‌شود و شما فقط یکی از این دو را می‌توانید داشته باشید.

در یک دیتاسنتر، معماری معمول شامل یک دیتابیس primary، یک کپی همزمان و چند کپی ناهمزمان است. این توپولوژی در چند دیتاسنتر هم تکرار می‌شود. تنظیم «نیمه‌همزمان» تضمین می‌کند اگر یک replica ناهمزمان از دست برود، اپلیکیشن‌ها شدیداً آسیب نبینند. همین مصالحه‌ها برای تکثیر بین‌ناحیه‌ای هم اعمال می‌شود و اجازه می‌دهد اپلیکیشن‌ها در یک ناحیه حتی اگر ناحیهٔ دیگر down شود به کار ادامه دهند. اما اگر replica همزمان شکست بخورد، کل اپلیکیشن متوقف می‌شود تا از ناسازگاری جلوگیری شود؛ به همین دلیل در غلبه بر خرابی همان کپی همزمان معمولاً primary انتخاب می‌شود. این توپولوژی نیمه‌همزمان یک تعادل مؤثر ایجاد می‌کند.

PostgreSQL که ریشه‌اش به دههٔ ۹۰ در Berkeley برمی‌گردد، ابتدا با معماری یکپارچه طراحی شد. برای تبدیل آن به یک سیستم توزیع‌شده، ما به دو جنبهٔ تکثیر شدیداً تکیه می‌کنیم: تکثیر منطقی و تکثیر جریانی. یک گزینهٔ سوم یعنی cascading replication روی logical و streaming ساخته شده است.

قبل از اینکه وارد نقش replication در ساخت کلاستر توزیع‌شده شویم، یک اشارهٔ کوتاه به WAL لازم است. در هر دیتابیس رابطه‌ای (از MySQL تا Oracle)، دوام در ACID با WAL به دست می‌آید. تغییرات دیتابیس که ابتدا در حافظهٔ فرّار ذخیره می‌شوند و به‌صورت ناهمزمان روی دیسک flush می‌شوند، اول به شکل ترتیبی در یک فایل WAL روی دیسک ثبت می‌شوند. این باعث می‌شود در صورت crash بتوان داده را از طریق recovery برگرداند.

این ویژگی در ساخت سیستم‌های replication حیاتی است، چون به ما اجازه می‌دهد واحدهای کار (هر entry لاگ) را ضبط و تکثیر کنیم.

در حالت streaming replication، موضوع ساده است: یک کپی یک اتصال TCP برقرار می‌کند و entryهای WAL را از primary به یک کپی دیگر stream می‌کند. مزیت مهم آن عملکرد است؛ می‌تواند تغییرات را تا حدود یک ترابایت در ثانیه با تأخیر کم ثبت کند (البته منابع تأخیر را بعداً پوشش می‌دهیم). اما یک نکتهٔ منفی دارد: رویکرد all-or-nothing است و چون در سطح بلاک‌های فایل‌سیستم تکثیر می‌کند، همهٔ تغییرات همهٔ آبجکت‌های Postgres را به هر کپی می‌فرستد.

logical replication نسخهٔ جدیدتر است و در سطح SQL عمل می‌کند و انعطاف می‌دهد که داده را در سطح جدول، ردیف یا ستون تکثیر کنید. اما امکان تکثیر تغییرات DDL وجود ندارد و ابزارهای سفارشی لازم می‌شود، و از طرفی در مقیاس چندترابایتی چالش‌های مقیاس‌پذیری دارد.

مدیریت کلاستر (Cluster Management)

یکی از دلایل اصلی مدیریت کلاستر، رسیدگی به خرابی‌های دیتابیس است. خرابی‌ها، چه منطقی مثل خراب‌شدن داده و چه شدیدتر مثل خرابی سخت‌افزاری به علت بلایای طبیعی، اجتناب‌ناپذیرند. غلبه بر خرابی دستی در این وضعیت‌ها دردسرناک است. علاوه بر این، حدود ۵٪ از سرورهای commodity کلاودفلر در هر لحظه معیوب هستند؛ یعنی در یک ناوگان هزاران‌تایی از سرورها و چند دیتاسنتر، خرابی‌های جاری همیشه وجود دارد. یک سیستم خودکار مدیریت کلاستر برای مدیریت کارآمد این خرابی‌های متنوع و حیاتی ضروری است.

تیم stolon را انتخاب کرد؛ یک سیستم متن‌باز مدیریت کلاستر که با Go نوشته شده و به‌عنوان یک لایهٔ نازک روی کلاستر PostgreSQL اجرا می‌شود، با رابط native برای PostgreSQL و پشتیبانی از افزونگی چندسایتی. می‌توان یک کلاستر stolon را طوری مستقر کرد که بین چند کلاستر PostgreSQL توزیع شود، چه در یک ناحیه و چه در چند ناحیه.

ویژگی‌های stolon شامل غلبه بر خرابی پایدار با حداقل false positive است. Keeper Nodeها به‌عنوان فرایندهای والد عمل می‌کنند که تغییرات PostgreSQL را مدیریت می‌کنند. Sentinel Nodeها نقش orchestrator دارند، سلامت مؤلفه‌های Postgres را مانیتور می‌کنند و تصمیم می‌گیرند، مثل آغاز انتخابات برای primary جدید. Proxy Nodeها اتصال‌های کلاینت را مدیریت می‌کنند و تضمین می‌کنند فقط یک primary نوشتن وجود داشته باشد تا وضعیت multi-master رخ ندهد.

cloudflare چگونه خوشه‌های توزیع‌شدهٔ postgresql را اداره می‌کند؟

شکل ۲: معماری stolon

پولینگ اتصال (Connection Pooling)

اتصال‌های دیتابیس منابع محدودی هستند و به خاطر سربار ذاتی باید بهینه مدیریت شوند.

اتصال‌های PostgreSQL روی TCP هستند که شامل three-way handshake و handshake SSL برای امنیت ارتباط می‌شود. هر اتصال یک فرایند جداگانه در سطح OS اختصاص می‌دهد و فرایند اصلی postmaster باید fork انجام دهد، که CPU و حافظه مصرف می‌کند. وقتی هزاران اتصال همزمان باز می‌شود، هم descriptorهای سوکت و هم زمان CPU اختصاص‌یافته برای پردازش تراکنش کم می‌شود.

یک connection pooler سمت سرور تعداد ثابتی اتصال دیتابیس را مدیریت می‌کند اما یک رابط سازگار با PostgreSQL به کلاینت‌ها ارائه می‌دهد. به‌عنوان واسط، تعداد اتصال‌های باز را با بازیافت اتصال‌ها کاهش می‌دهد، وقتی کلاینت‌ها از طریق آن به دیتابیس وصل می‌شوند.

این کار کنترل منابع tenant را متمرکز می‌کند و به تیم اجازه می‌دهد تعداد اتصال‌های تخصیص‌یافته به هر سرویس upstream اپلیکیشن را تنظیم کند. بهبودهای کلاودفلر روی PgBouncer شامل قابلیت‌هایی الهام‌گرفته از TCP Vegas است؛ الگوریتم جلوگیری از ازدحام TCP که با محدودکردن throughput کلی tenant، جداسازی منابع چندمستاجری را سخت‌گیرانه‌تر می‌کند.

کلاودفلر PgBouncer را انتخاب کرد چون با پروتکل PostgreSQL سازگار است: کلاینت‌ها می‌توانند به PgBouncer وصل شوند و کوئری‌ها را عادی ارسال کنند، که جابه‌جایی دیتابیس و غلبه بر خرابی را ساده می‌کند. PgBouncer یک سرور سبک تک‌فرایندی است که اتصال‌ها را به‌صورت ناهمزمان مدیریت می‌کند و می‌تواند اتصال‌های همزمان بیشتری نسبت به PostgreSQL تحمل کند.

cloudflare چگونه خوشه‌های توزیع‌شدهٔ postgresql را اداره می‌کند؟

شکل ۳: PgBouncer چطور کار می‌کند

PgBouncer اتصال‌های سمت کلاینت را (جدا از اتصال‌های مستقیم به PostgreSQL) معرفی می‌کند و از یک مدل non-blocking برای I/O شبکه استفاده می‌کند، با یک thread واحد و مکانیزم epoll سیستم‌عامل برای مانیتور رویدادها.

cloudflare چگونه خوشه‌های توزیع‌شدهٔ postgresql را اداره می‌کند؟

شکل ۴: یک فرایند PgBouncer

برخلاف مدل «یک thread برای هر اتصال» در PostgreSQL، حلقه رویداد تک‌ریسمانی PgBouncer مصرف حافظه را کم می‌کند چون از چندین stack thread اجتناب می‌کند و بهره‌وری CPU را بهتر می‌کند چون درخواست‌های همه کلاینت‌ها را در یک thread سرویس می‌دهد و زمان CPU روی threadهای idle هدر نمی‌رود.

برای اینکه چند فرایند تک‌ریسمانی PgBouncer بتوانند از همه هسته‌های CPU روی یک ماشین استفاده کنند، راه‌حل از دل سیستم‌عامل آمد: تیم گزینهٔ SO_REUSEPORT را به سوکت اضافه کرد تا چند سوکتِ چند فرایند بتوانند همزمان روی یک پورت گوش کنند.

توزیع بار

کلاودفلر از load balancer یعنی HAProxy استفاده می‌کند تا کوئری‌های ورودی دیتابیس را به‌طور یکنواخت بین چند سرور PostgreSQL توزیع کند و از overload روی یک سرور جلوگیری کند. مشابه PgBouncer، HAProxy با ریدایرکت ترافیک از سرورهای خراب به سرورهای سالم، دسترس‌پذیری بالا و تحمل خطا فراهم می‌کند و downtime ناشی از نمونه‌های تنزل‌یافته را کاهش می‌دهد. HAProxy اتصال‌های TCP در لایه ۴ را با سربار کم مدیریت می‌کند و از system call به نام kernel splice استفاده می‌کند. جریان‌های TCP ورودی و خروجی داخل خود کرنل به هم متصل می‌شوند و داده بدون کپی شدن به userspace منتقل می‌شود.

چالش‌ها و راه‌حل‌ها

بیایید چالش‌های زیرساخت دیتابیس را بررسی کنیم و چند نکته عملکردی برای رسیدن به دسترس‌پذیری بالا در لبه به اشتراک بگذاریم. replication lag در ترافیک سنگین و عملیات write-heavy مثل اجرای ETL خیلی برجسته می‌شود. هر عملیات نوشتن حجیم مثل migration داده و حذف‌های مربوط به انطباق GDPR، و حتی فشرده‌سازی خودکار ذخیره‌سازی (autovacuum) هم replication lag را تشدید می‌کند.

تیم یک SLO برای replication lag حدود ۶۰ ثانیه هدف‌گذاری می‌کند و به تیم‌های اپلیکیشن مطابق آن توصیه می‌کند. برای کمینه‌کردن lag، نوشتن‌های SQL به دسته‌های کوچک‌تر (batch) تقسیم می‌شوند تا replication روان‌تر شود. سازگاری read-after-write با کش‌کردن یا خواندن مستقیم پس از نوشتن از primary یا از یک کپی همزمان حفظ می‌شود. یک رویکرد نامتعارف برای دورزدن lag این است که همه کپی ها از کلاستر بیرون انداخته شوند و فقط primary باقی بماند. این در عمل مؤثر بوده، اما نیاز به درک عمیق از بار کوئری‌ها و تغییرات احتمالی سیستم دارد. می‌توانید این را مثل کلیدواژهٔ unsafe در Rust در نظر بگیرید.

در سال ۲۰۲۰، یک رخداد بزرگ عملکرد و دسترس‌پذیری دیتابیس را در کلاودفلر شدیداً تحت تأثیر قرار داد. خرابی‌های آبشاری باعث افت ۷۵٪ در دسترس‌پذیری API و کندتر شدن ۸۰ برابری داشبوردها شد. نمونه‌های primary دیتابیس در هر دو ناحیه اصلی و standby یک غلبه بر خرابی انجام دادند، اما primary جدید در ناحیه اصلی زیر بار دوام نیاورد و دوباره شکست خورد. چون کپی همزمانی برای ارتقا وجود نداشت، یک تصمیم حیاتی لازم بود: ارتقای یک کپی ناهمزمان با احتمال از دست دادن داده یا تخلیه نواحی به سمت کلاستر standby که downtime بیشتری ایجاد می‌کرد.

از دست دادن داده قابل قبول نیست، پس گزینهٔ دوم انتخاب شد. بررسی بیشتر نشان داد یک سوئیچ شبکه به‌صورت جزئی خراب شده و در حالت تنزل‌یافته کار می‌کرد و ارتباط بین هر دو کلاستر etcd بین‌ناحیه‌ای را مسدود می‌کرد.

این عدم ارتباط باعث شد پروتکل Raft وارد وضعیت deadlock شود و کلاسترها read-only شوند. غلبه بر خرابی  و resync کردن ناکارآمدی‌های PostgreSQL را آشکار کرد، مخصوصاً در زمان resync. این تنظیم، خرابی کامل مثل crash ماشین را خوب مدیریت می‌کند، اما وقتی گره‌های کلاستر Raft شروع به ارائه اطلاعات متناقض می‌کنند، رفتارهای تعریف‌نشده مشکل‌ساز می‌شود.

مثلاً گره‌های ۱، ۲ و ۳ به علت سوئیچ معیوب ارتباط شبکه تنزل‌یافته داشتند. گره ۱ اشتباه فکر کرد گره ۳ دیگر رهبر نیست، و این باعث مجموعه‌ای از انتخابات رهبری شکست‌خورده شد و deadlock ایجاد کرد. این deadlock کلاستر را وارد حالت read-only کرد، ارتباط بین نواحی را مختل کرد و غلبه بر خرابی به کپی را تحریک کرد.

cloudflare چگونه خوشه‌های توزیع‌شدهٔ postgresql را اداره می‌کند؟

شکل ۵: اطلاعات متناقض در کلاستر

در زمان غلبه بر خرابی، کپی همزمان ارتقا داده می‌شود و این نیاز دارد که primary قدیمی برخی تراکنش‌های متعهد شده را undo کند چون ممکن است تاریخچه تراکنش‌ها واگرا شده باشد. بعد از باز کردن تاریخچه واگرا، کپی همزمان باید تراکنش‌های جدید را از primary اصلاح‌شده دریافت و replay کند که در مورد ما به دلیل نبود کپی همزمان برای جذب دادهٔ جدید شکست خورد و downtime رخ داد.

مسائل شناسایی‌شده شامل: یک خرابی سخت‌افزاری، یک خطای بیزانسی نادر با Raft، و زمان طولانی همگام‌سازی مجدد PostgreSQL بود. تیم تصمیم گرفت روی حل مورد سوم تمرکز کند. بررسی لاگ‌ها نشان داد بیشتر زمان در rsync صرف می‌شود، چون هنگام resync بیش از ۱.۵ ترابایت فایل log کپی می‌شد.

cloudflare چگونه خوشه‌های توزیع‌شدهٔ postgresql را اداره می‌کند؟

شکل ۶: pg_rewind همه لاگ‌ها را کپی می‌کند، حتی سگمنت‌های مشترک قبل از آخرین نقطه واگرایی

راه‌حل این بود که PostgreSQL از داخل بهینه شود تا فقط فایل‌های لازم از آخرین نقطه واگرایی کپی شوند و حجم انتقال داده به ۵٪ مقدار اولیه کاهش پیدا کند. این بهینه‌سازی داخلی PostgreSQL زمان ساخت دوباره کپی را از بیش از ۲ ساعت به ۵ دقیقه رساند، یعنی ۹۵٪ سریع‌تر.

cloudflare چگونه خوشه‌های توزیع‌شدهٔ postgresql را اداره می‌کند؟

شکل ۷: pg_rewind پچ‌شده فقط لاگ‌ها از آخرین نقطه واگرایی را کپی می‌کند

درس‌هایی که از رخداد بزرگ مقیاس گرفته شد شامل:

  • پیش‌بینی حالت‌های تنزل‌یافته، نه فقط حالت‌های کاملاً خراب

  • سرمایه‌گذاری روی مشارکت‌های متن‌باز برای ایجاد تخصص داخلی؛ پچ متن‌باز ارائه‌شده به PostgreSQL CommitFest کمک می‌کند

  • اهمیت ساختن و اصلاح نرم‌افزار در داخل سازمان

دسترسی به داده از لبه (Access Data from the Edge)

نگه داشتن یک کلاستر در یک ناحیه کافی نیست. برای مقابله با خرابی‌های مختلف، از جمله سناریوهای سخت مثل خرابی سخت‌افزاری بیزانسی، باید کلاسترهای PostgreSQL را بین چند ناحیه توزیع کنید. این رویکرد «کلاستر از کلاسترها» (cluster-of-clusters) از دید Cloudflare Workers تاب‌آوری را بیشتر می‌کند. کلاودفلر از یک ناحیه primary در آمریکا فراتر رفت و اروپا و آسیا را هم اضافه کرد و یک مدل hub-and-spoke با استفاده از streaming replication ساخت.

همگام‌سازی بین نواحی حیاتی است و مسائلی مثل replication lag را شامل می‌شود. وقتی lag زیاد می‌شود، برگرداندن ترافیک به ناحیه primary کمک می‌کند SLAها برای تیم‌های اپلیکیشن حفظ شود. این راهبرد سیستم را مقاوم‌تر می‌کند و اثر خرابی‌های احتمالی را کم می‌کند.

یک کلاستر توزیع‌شده مزیت‌های بزرگی دارد، مخصوصاً در غلبه بر خرابی هوشمند. با انتخاب راهبردی ناحیه primary بر اساس عواملی مثل بار فعلی، ظرفیت موجود، یا منطقه زمانی («خورشید را دنبال کن» یا follow the sun)، می‌توان برای تأخیر کمتر در ساعات فعال مناطق مختلف دنیا بهینه کرد. این رویکرد پویا محدودیت «تک primary» در PostgreSQL را دور می‌زند.

ملاحظات ظرفیت هم تصمیم‌ها را هدایت می‌کند: بعضی نواحی ظرفیت بیشتری دارند و چالش‌های لجستیکی مثل ارسال سخت‌افزار در دوران COVID هم روی تصمیم‌ها اثر می‌گذارد. الگوهای ترافیک و نیازهای انطباق هم انتخاب ناحیه را شکل می‌دهند و اجازه می‌دهند نیازهای مقرراتی خاص به شکل کارآمد پوشش داده شوند. رویکرد توزیع‌شده به کلاودفلر کمک می‌کند این چالش‌ها را بهتر مدیریت کند.

گسترش PostgreSQL به چند ناحیه و دستیابی به غلبه بر خرابی سریع با ابزارهایی مثل pg_rewind همانطور که گفته شد کارآمد است، اما پیچیدگی وقتی بالا می‌رود که وابستگی‌های اپلیکیشن وارد بازی شوند. در حالی که مهاجرت دیتابیس قابل مدیریت است، غلبه بر خرابی دادن کل اکوسیستم اپلیکیشن، شامل مؤلفه‌های توزیع‌شده مثل Kafka message queue، دشوار است. در زمان سوییچ ناحیه، درک کامل گراف وابستگی اپلیکیشن حیاتی است.

cloudflare چگونه خوشه‌های توزیع‌شدهٔ postgresql را اداره می‌کند؟

شکل ۸: گراف کامل وابستگی اپلیکیشن

با وجود تلاش‌های مداوم برای اتوماسیون، هماهنگی بین تیم‌ها و حتی بین سازمان‌های مختلف حیاتی می‌شود. توالی سوییچ سرویس‌ها بین نواحی شامل در نظر گرفتن کلاسترهای دیتابیس، سرویس‌های اپلیکیشن (مثل احراز هویت و پیکربندی) در کلاسترهای Kubernetes، و وابستگی آن‌ها به زیرساخت مرکزی مثل R2 و SSL است.

پترندهای دیتابیس (Database Trends)

به‌عنوان افرادِ درگیرِ کار، چند روند کلیدی در دیتابیس‌های رابطه‌ای دیده‌ایم. اول، حرکت به سمت تعبیه داده در لبه است؛ استفاده از یک مونولیت یا PostgreSQL در چند ناحیه، همراه با دیتابیس‌های embedded مثل SQLite برای پردازش واقعی در لبه. حیاتی است که SQLite در لبه با داده‌های PostgreSQL در هسته/مکان‌های مرکزی همگام نگه داشته شود. همچنین، سازگار بودن SQLite با PostgreSQL wire-protocol برای ادغام بدون دردسر مهم است.

روند دیگر شامل ماندگاری در لبه است، جایی که Cloudflare Workers داده سمت کلاینت را پردازش می‌کند. همچنین یک شیفت مهم به سمت هم‌مکانی ذخیره‌سازی و محاسبه دیده می‌شود که با قابلیت‌هایی مثل Smart Placement نشان داده می‌شود.

cloudflare چگونه خوشه‌های توزیع‌شدهٔ postgresql را اداره می‌کند؟

شکل ۹: Cloudflare Workers هم‌مکان با کلاستر دیتابیس

این کار تأخیر را کم می‌کند چون از پرش‌های شبکه بین نواحی به سمت یک ذخیره‌سازی مرکزی جلوگیری می‌کند و به این واقعیت پاسخ می‌دهد که بسیاری از اپلیکیشن‌های کلاینت زمان زیادی را صرف گفتگو با دیتابیس‌ها می‌کنند.

در نهایت، محلی‌سازی داده، مخصوصاً در اروپا با PostgreSQL، یک چالش است. logical replication به‌عنوان یک محور جدی مطرح است چون انعطاف تکثیر در سطح ردیف یا ستون را می‌دهد، هرچند هنوز در فاز اکتشافی است. انتظار این است که logical replication نقش مهمی در حل این چالش بازی کند.

تفاوت‌های اصلی بین Contract Testing و Schema Validation چیست؟
چگونه نتفلیکس ۲۳۸ میلیون عضویت خود را مدیریت می‌کند؟

دیدگاهتان را بنویسید

سبد خرید
علاقه‌مندی‌ها
مشاهدات اخیر
دسته بندی ها