ویرگول
ورودثبت نام
Hussein Mahmoudabadi
Hussein Mahmoudabadiمهندس نرم افزار
Hussein Mahmoudabadi
Hussein Mahmoudabadi
خواندن ۵ دقیقه·۳ روز پیش

وقتی سیستم‌های Large-Scale تحت فشارند: تحلیلی از رفتار Fault-Tolerant در بلک‌فرایدی اسنپ‌پی

سیستم‌های Large-Scale چگونه در لحظه‌های بحرانی زنده می‌مانند؟

از مفاهیم Fault Tolerance و Graceful Degradation تا ماجرای بلک‌فرایدی اسنپ‌پی

طراحی سیستم‌های نرم‌افزاری Large-Scale همیشه با یک واقعیت تلخ همراه است: در سیستم‌های بزرگ، از کارافتادن بخش‌هایی از سامانه یک واقعیت طبیعی است

هیچ سامانه پیچیده‌ای نیست که بدون وقفه و بی‌خطا کار کند. سرورها گاهی از مدار خارج می‌شوند، دیتابیس‌ها گاهی تحت فشار زیاد دچار deadlock یا contention می‌شوند، شبکه ممکن است برای چند لحظه قطع یا ناپایدار شود و سرویس‌هایی که به آن‌ها وابسته‌ایم هر لحظه ممکن است پاسخ‌گو نباشند.در چنین شرایطی، آنچه یک سرویس را «معتبر» جلوه می‌دهد، نبودِ خطا نیست؛

بلکه نحوه‌ی واکنش سیستم هنگام خطاست.

اینجاست که مفاهیم کلیدی مثل Fault Tolerance، Graceful Degradation و Resilience نقش اصلی را پیدا می‌کنند.

برای اینکه بتوانیم ماجرای بلک‌فرایدی ایران را تحلیل کنیم، ابتدا باید این مفاهیم را درست بشناسیم.

Fault Tolerance چیست؟

Fault Tolerance یعنی سیستم به‌گونه‌ای طراحی شده باشد که اگر بخشی از آن خراب شد، کل سیستم از کار نیفتد.

این مفهوم شامل چند ویژگی مهم است:

سیستم باید بتواند خطا را تشخیص دهد؛

بخش خراب را از مسیر اصلی جدا کند؛

و یک مسیر جایگزین برای ادامه‌ی کار فعال کند.

هدف Fault Tolerance این نیست که جلوی وقوع خطا را بگیرد؛ چنین چیزی حتی در مقیاس شرکت‌هایی مثل آمازون و نتفلیکس هم غیرممکن است. هدف واقعی این است که خطا در همان بخش محدود باقی بماند و اجاز گسترش آن به کل سیستم داده نشود.

وقتی یک دیتابیس Replica دارد، یک سرویس چندین Instance اجرا می‌کند، یا یک سیستم Load Balancer هوشمند دارد، این‌ها همه مصادیقی از Fault Tolerance هستند.

کاربر حتی نباید بفهمد که جایی در پشت‌صحنه یکی از اجزا از مدار خارج شده است.

Redundancy در Fault Tolerance
Redundancy در Fault Tolerance

Graceful Degradation چیست؟

Graceful Degradation برعکس Fault Tolerance در مورد «ادامه دادن کامل» نیست.

گاهی شرایط بحرانی آن‌قدر شدید است که امکان ادامه‌ی سرویس با ظرفیت کامل وجود ندارد.

در چنین لحظه‌ای، اگر سیستم تلاش کند مانند همیشه رفتار کند، به احتمال زیاد کاملاً سقوط خواهد کرد.

Graceful Degradation یعنی سیستم تصمیم می‌گیرد بخشی از سرویس را قربانی کند تا بخش حیاتی پابرجا بماند.

در واقع، سیستم ضعیف‌تر می‌شود، کم‌امکانات‌تر می‌شود، اما زنده می‌ماند.

برای مثال، سرویس‌های large-scale معمولاً با کاهش عملکرد تدریجی از فروپاشی کامل جلوگیری می‌کنند. نتفلیکس وقتی پهنای باند کم می‌شود، کیفیت ویدیو را پایین می‌آورد تا پخش ادامه پیدا کند؛ و GitHub نیز در زمان ترافیک بالا، ابتدا بخش‌های غیرحیاتی مثل جست‌وجو، ایندکسینگ و عملیات background را کند یا محدود می‌کند تا سرویس‌های اصلی مثل push، pull و احراز هویت پایدار بمانند. این رفتارها نمونه‌های روشن و مستند از Graceful Degradation در صنعت هستند

Graceful Degradation فلسفه‌ای بسیار مهم در Large-Scale است:

بهتر است سیستم کمی ضعیف شود تا اینکه کاملاً از دسترس خارج شود.

 

Resilience؛ ترکیب هوشمندانه‌ی تحمل خطا و کاهش عملکرد کنترل‌شده

Resilience مفهوم بزرگ‌تری است که Fault Tolerance و Graceful Degradation را در خود دارد.

سیستم Resilient سیستمی است که می‌داند چه زمانی باید مقاوم باشد و چه زمانی منعطف.

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

این سیستم‌ها معمولاً ابزارهای زیر را در هسته‌ی خود دارند:

 Redundancy برای داشتن نقاط پشتیبان

Circuit Breaker برای جلوگیری از سرایت خطا،

Message Queue برای مدیریت جهش‌های ناگهانی ترافیک،

عملیات Idempotent برای جلوگیری از خطاهای ناشی از Retry،

Observability برای مشاهدهٔ زندهٔ رفتار سیستم،

و Auto-Healing برای بازیابی خودکار سرویس‌های ازکارافتاده.

وقتی این عناصر کنار هم قرار می‌گیرند، نتیجه سیستمی است که نه فقط به‌سختی می‌میرد، بلکه در هنگام بحران خودش را مدیریت می‌کند.

Resilient Architecture
Resilient Architecture

و حالا می‌رسیم به روایت واقعی ماجرا؛  بحرانی که بسیاری از کاربران اسنپ‌پی و فروشگاه‌های شریکش تجربه کردن. در یکی از کمپین‌های گذشته، اسنپ‌پی محصولاتی با تخفیف‌های غیرمعمول، مثل آیفون یا مک‌بوک، به نمایش گذاشت چیزی که طبیعتاً موج بزرگی از ترافیک ایجاد میکنه. کاربران روی « خرید محصول » کلیک می‌کردند و به سایت فروشنده منتقل می‌شدند؛ اما در بسیاری از موارد، چیزی جز صفحه سفید، خطای ۵۰۳ یا حتی ۴۰۴ نبود.

مشکل نخست این بود که بسیاری از فروشگاه‌ها عملاً هیچ‌گونه Fault Tolerance نداشتند.
وقتی هزاران کاربر به‌طور هم‌زمان وارد یک سایت می‌شوند، سیستمی که تنها یک سرور دارد، محکوم است زیر فشار سقوط کند. اگر تنها یک Node تمام بار را تحمل کند، در لحظه ورود ترافیک سنگین نه فرصت بازیابی دارد و نه امکان مقیاس‌پذیری؛ نتیجه، همان صفحه سفید آشناست.

مشکل دوم، نبود Graceful Degradation بود. در یک معماری درست، زمانی که ظرفیت پردازش تمام می‌شود، سرویس باید نسخه ساده‌تری از خود را ارائه بده پیامی مانند «لطفاً چند لحظه بعد تلاش کنید» یا ورود موقت کاربر به یک Waiting Room. اما در این مورد، وقتی سیستم به مرز توانش رسید، به‌جای ضعیف‌تر شدن، مستقیماً سقوط کرد. این رفتار نقطه مقابل Graceful Degradation است: سیستم به‌جای کم‌کردن سطح خدمات، کل سرویس را از دسترس خارج کرد.

مشکل سوم، نبود Circuit Breaker در مسیر پرداخت بود.
وقتی فروشگاه مقصد Down شده بود، در معماری درست، سیستم پرداخت باید قطع اتصال را تشخیص دهد و مسیر انتقال کاربر را ببندد. اما چون چنین مکانیزمی وجود نداشت، اسنپ‌پی همچنان کاربران را به سرورِ ازکارافتاده منتقل می‌کرد. نتیجه این می‌شود که کاربر بارها با سروری روبه‌رو شود که از اساس توان پاسخ‌گویی ندارد نوعی هدایت ترافیک به ناکجاآباد.

اما مشکل چهارم پیچیده‌تره و معمولاً نادیده گرفته می‌شود. بسیاری می‌گویند «ای کاش Queue وجود داشت»، اما واقعیت اینه که درخواست‌های یک فروشگاه آنلاین، به‌ویژه درخواست‌های نمایش صفحات مثل Home) یا (Product Page ، همگی synchronous هستند و کاربر انتظار پاسخ لحظه‌ای دارد؛ بنابراین استفاده از Queue در این نقطه کمک چندانی نمی‌کند. مسئله اصلی این بود که معماری پشت فروشگاه‌ها Availability-first نبود. در چنین شرایطی، به‌جای اینکه کل بار روی دیتابیس اصلی قرار بگیرد، باید داده‌ها در لایه نمایش روی Cache، Replicaهای متعدد، یا datastoreهای replicated قرار می‌گرفتند. طبق اصل CAP، لایه نمایش در E-commerce نیازی به Strong Consistency ندارد؛ کافی است موجودی و اطلاعات محصول با کمی تأخیر به‌روزرسانی شود، اما صفحه برای کاربر باز شود. نبود این معماری باعث شد بار روی یک دیتابیس واحد بنشیند و سیستم حتی فرصت نفس‌کشیدن نداشته باشد.

در نهایت، مشکلی باقی می‌ماند که معمولاً از خود خرابی خطرناک‌تر است: ضعف در Observability. بسیاری از این سرویس‌ها نمی‌دانستند دقیقاً کدام بخش سقوط کرده است. وقتی یک سامانه چشم نداشته باشد، بازیابی نه‌تنها دشوارتر، بلکه طولانی‌تر هم می‌شود. داشتن ابزارهایی مثل tracing، متریک‌های لحظه‌ای و logهای قابل اعتماد، چیزی است که حداقل به تیم عملیات می‌گوید از کجا شروع کند.

این مجموعه مشکلات دقیقاً همان چیزهایی است که شرکت‌های جهانی سال‌هاست با استفاده از الگوهای Resilience حل کرده‌اند. آنجا سیستم‌ها می‌دانند که ترافیک ناگهانی یک اتفاق عجیب نیست، بلکه بخشی از زندگی یک سرویس بزرگ است؛ و معماری آن‌ها به‌جای فروپاشی کامل، به‌تدریج سطح خدمات را کاهش می‌دهد و همچنان زنده می‌ماند.

اگر این مطلب براتون مفید بود خوشحال میشم نظرتون رو بدونم و با دوستانتون به اشتراک بذارید.

منابع :

Fault-Tolerant Event-Driven Systems: Techniques and Best Practices

Cost-Resilience Trade-off in Large-Scale Distributed Systems


اسنپ‌پیبلک فرایدی
۱
۲
Hussein Mahmoudabadi
Hussein Mahmoudabadi
مهندس نرم افزار
شاید از این پست‌ها خوشتان بیاید