Scale تا میلیونها کاربر
سامانهٔ فروش بلیت پروژهٔ ۱۱ را مقیاس میدهید: load balancing، autoscaling، cache چندلایه، read replica، sharding و محافظت در اوج بار. با آزمون بار ثابت میکنید که با افزودن سرور، ظرفیت بالا میرود.
در این صفحه
هدف
در پایان این پروژه:
- سامانه با افزودن سرور، بار بیشتری میکشد و این را با عدد نشان میدهید.
- تعداد نسخههای هر سرویس با بالا و پایین رفتن بار، خودکار تغییر میکند.
- داده میان چند پایگاه داده پخش شده و هیچ پایگاه دادهای گلوگاه کل سیستم نیست.
- در لحظهٔ شروع فروش که بار دهها برابر میشود، سامانه کند میشود ولی از کار نمیافتد.
- یک برنامهٔ ظرفیت دارید که میگوید برای ده میلیون کاربر چند سرور لازم است و چرا.
از کاربر تا عدد
پیش از هر تغییری، باید بدانید «میلیونها کاربر» یعنی چه مقدار بار. این برآورد را در گام اول خودتان میسازید:
از همین جدول دو نتیجه بیرون میآید. خواندن ده برابر نوشتن است، پس این دو مسیر جدا مقیاس میگیرند. و ۲۰۰ هزار نفر برای ۵۰ هزار صندلی رقابت میکنند، پس بیشتر درخواستهای خرید باید زود و ارزان رد شوند.
معماری هدف
هر لایه یک پرسش را جواب میدهد:
- CDN و cache لبه: کدام درخواستها اصلاً نباید به سرور شما برسند؟
- load balancer: بار چطور میان نسخهها پخش میشود و نسخهٔ خراب چطور کنار گذاشته میشود؟
- waiting room: وقتی تقاضا از ظرفیت بیشتر است، چه کسی وارد میشود و بقیه چه میبینند؟
- cache و read replica: خواندنهای پرتکرار چطور از پایگاه دادهٔ اصلی دور میمانند؟
- shard router: هر سفارش در کدام پایگاه داده است؟
- partition در Kafka: کار ناهمزمان چطور میان مصرفکنندهها پخش میشود و ترتیب کجا حفظ میشود؟
پخش داده با sharding
کلید sharding شناسهٔ رویداد است. همهٔ صندلیها و سفارشهای یک رویداد در یک shard میمانند، پس رزرو همچنان با یک تراکنش محلی انجام میشود. consistent hashing باعث میشود با افزودن یک shard، فقط بخش کوچکی از داده جابهجا شود.
مقایسه با دنیای Python
پیشنیازها
- پروژهٔ ۱۱ کامل: همین سامانه را مقیاس میدهید.
- همهٔ درسهای فاز ۷.
- از فاز ۵: profiling با
pprofو benchmark.
گامهای پروژه
خط مبنا و نخستین گلوگاه
برآورد ظرفیت، تعریف SLO، سناریوهای آزمون بار و اندازهگیری وضعیت فعلی.
معیار پذیرش: گزارشی دارید که میگوید سامانه با یک نسخه از هر سرویس تا چه نرخی SLO را نگه میدارد و نخستین جایی که میشکند کجاست. هر گام بعدی با همین سناریوها سنجیده میشود.
نسخههای متعدد و load balancing
حذف وضعیت از حافظهٔ سرویسها، load balancer لایهٔ ۷، health check، تخلیهٔ اتصال هنگام خاموشی و پخش بار gRPC در سمت کلاینت.
معیار پذیرش: با سه نسخه از هر سرویس، بار با اختلاف کمتر از ۱۰ درصد میان نسخهها پخش میشود. خاموش کردن یک نسخه زیر بار، هیچ درخواستی را خراب نمیکند.
autoscaling
مقیاس خودکار بر پایهٔ CPU، نرخ درخواست و عقبافتادگی مصرفکنندههای Kafka.
معیار پذیرش: با پنج برابر شدن بار، تعداد نسخهها در کمتر از یک دقیقه بالا میرود و SLO برمیگردد. با فروکش کردن بار، نسخهها کم میشوند.
cache چندلایه
سرآیندهای cache برای CDN، Redis Cluster، cache درون پروسه، جلوگیری از stampede و باطل کردن cache با رویداد.
معیار پذیرش: بیش از ۹۵ درصد خواندنهای فهرست رویدادها به پایگاه داده نمیرسد. با منقضی شدن یک کلید پرمصرف، فقط یک درخواست به پایگاه داده میرود.
مقیاس خواندن
read replica، برخورد با تأخیر replication و یک مدل خواندن جدا برای
catalogکه از رویدادها ساخته میشود.معیار پذیرش: کاربر پس از خرید، بلیت خودش را همیشه میبیند، حتی وقتی replica عقب است. بار خواندن روی پایگاه دادهٔ اصلی نزدیک به صفر است.
sharding
مسیریاب shard با consistent hashing، افزودن shard تازه و جابهجایی داده بدون توقف.
معیار پذیرش: با دو برابر شدن تعداد shard و نسخهها، نرخ خرید موفق دستکم ۱٫۸ برابر میشود. هنگام افزودن shard، هیچ سفارشی گم نمیشود و هیچ صندلیای دو بار فروخته نمیشود.
محافظت در اوج بار
waiting room برای کنترل ورود، rate limit توزیعشده، رد کردن زودهنگام بار اضافه و افت کیفیت کنترلشده.
معیار پذیرش: با باری ده برابر ظرفیت، کاربرانی که وارد شدهاند با SLO عادی خرید میکنند. بقیه در صف میمانند و پاسخ سریع میگیرند. هیچ سرویسی از کار نمیافتد.
آزمون شکست و برنامهٔ ظرفیت
از کار انداختن node، قطع شبکه میان سرویسها، پخش در چند zone و نوشتن برنامهٔ ظرفیت و هزینه.
معیار پذیرش: با از دست رفتن یک node زیر بار، نرخ خطا زیر ۰٫۱ درصد میماند. سند ظرفیت، با تکیه بر عددهای اندازهگیریشده، تعداد سرور لازم برای جدول برآورد بالا را حساب میکند.
چه چیزی را اندازه میگیرید
SLO این پروژه از اول مشخص است و همهٔ گامها با آن سنجیده میشوند:
تصمیمهای مهندسی که باید از آنها دفاع کنید
- کلید sharding: چرا شناسهٔ رویداد و نه شناسهٔ کاربر؟ با یک رویداد بسیار بزرگ که یک shard را پر میکند چه میکنید؟
- سازگاری خواندن: کجا دادهٔ کمی قدیمی پذیرفتنی است و کجا نه؟
- جای rate limit: در لبه، در gateway یا در هر سرویس؟
- صف یا رد کردن: درخواست اضافه را نگه میدارید یا همان لحظه رد میکنید؟ هزینهٔ هر کدام برای کاربر چیست؟
- هزینه: ارزانترین پیکربندیای که SLO را نگه میدارد کدام است؟
اشتباههای رایج
نتیجهٔ نهایی
- گزارش آزمون بار با نمودار ظرفیت پیش و پس از هر گام
- اثبات مقیاس خطی: نسبت دستکم ۱٫۸ با دو برابر شدن منابع
- autoscaling و waiting room فعال در خوشهٔ Kubernetes
- sharding با امکان افزودن shard بدون توقف
- گزارش آزمون شکست
- سند برنامهٔ ظرفیت و هزینه برای ده میلیون کاربر