چطور نتفلیکس ۲۶۰ میلیون استریم همزمان را بدون لودینگ (Buffering) مدیریت میکند؟
سختترین بخش مسئله، دقیقاً قبل از اینکه شما دکمه Play را فشار دهید حل شده است!
اگر وقت زیادی ندارید، لب مطلب اینجاست: ۱. ارسال ویدیو از ابر (Cloud) انجام نمیشود: نتفلیکس تمام سرورهای پخش ویدیوی خود (با نام Open Connect) را فیزیکی داخل دیتاسنتر ارائه دهندگان اینترنت (ISPها) قرار داده است. ۲. پیشبینی و دانلود شبانه: ویدیوها قبل از درخواست شما، در ساعات کمترافیک شب (۳ تا ۶ صبح) روی سرور محلی ISP شهر شما کپی میشوند. ۳. تطبیق لحظهای کیفیت (ABR): اپلیکیشن روی تلویزیون یا گوشی شما، لحظه به لحظه حجم بافر و سرعت اینترنت را چک میکند و قبل از اینکه فیلم گیر کند، کیفیت قطعه بعد را پایین میآورد.
چند وقت پیش وسط تماشای یک قسمت از سریال مورد علاقهام، وایفای خونهمون یک لحظه نوسان پیدا کرد. کیفیت تصویر حدود ۱۰ ثانیه کمی تار و بیکیفیت شد، اما بعد خیلی آروم و بیصدا دوباره شفاف و 4K شد. بدون هیچ چرخنده لودینگی (Spinner)، بدون هیچ توقفی (Stall) و بدون اینکه رو اعصاب برود!
این تجربه کوچک و روان، حاصل یک زنجیره بسیار طولانی و پیچیده مهندسی است؛ زنجیرهای که جالب است بدانید تقریباً هیچکدام از مراحلش زمانی که شما دکمه Play را میزنید اجرا نمیشود!
نتفلیکس در اوایل سال ۲۰۲۴ از مرز ۲۶۰ میلیون مشترک گذشت و تا امروز از ۳۰۰ میلیون کاربر عبور کرده است. فقط در یک شب از نوامبر ۲۰۲۴، ۶۵ میلیون استریم همزمان برای پخش زنده مسابقه بوکس روی این پلتفرم اجرا شد.
اما نتفلیکس چطور چنین بار غولآسایی را در سال ۲۰۲۶ بدون هنگ کردن مدیریت میکند؟ پاسخ کوتاه این است: سقوط یا موفقیت این سیستم، ساعتها قبل از ارسال اولین درخواست از خانه شما تعیین میشود. این کل داستان است و نگاه من را نسبت به کشینگ (Caching) و طراحی سیستم به کلی تغییر داد. بیایید با هم قدم به قدم پاسخش را بررسی کنیم.
چرا طراحیهای متداول و معمولی در این مقیاس شکست میخورند؟
طراحی اولیهای که اکثر ما مهندسان نرمافزار روی تختهواستبورد رسم میکنیم کاملاً منطقی به نظر میرسد:
فایلهای ویدیو را در چند دیتاسنتر بزرگ اصلی ذخیره میکنیم، یک CDN تجاری (مثل Cloudflare یا Fastly) جلوی آن قرار میدهیم و اجازه میدهیم با تماشای کاربران، کشها به مرور پر شوند (Pull-based Caching).
اما کافیست کمی ریاضیات پایهای انجام دهید تا ببینید این معماری چطور در یک پلک زدن فرو میریزد!
۶۵ میلیون استریم همزمان با متوسط بیتریت ۵ مگابیت بر ثانیه، معادل بیش از ۳۰۰ ترابیت بر ثانیه (300 Tbps) ترافیک مداوم است! هیچ خوشهای از سرورهای مرکزی قادر نیست چنین پهنای باندی را روی اینترنت عمومی ارسال کند. هزینههای پهنای باند (Transit Bills) به تنهایی شرکت را ورشکست میکند و لینکهای Peering شبکه قبل از سرورهای شما خفه میشوند. طبق آمارهای موسسه Sandvine، نتفلیکس به تنهایی سهمی دو رقمی از کل ترافیک دانلود (Downstream) اینترنت جهان را به خود اختصاص داده است.
علاوه بر این، کشهای On-demand یک نقطه شکست خاموش دیگر هم دارند: افتتاحیه سریالها (Premiere)!
وقتی فصل جدید یک سریال معروف ساعت ۱۲ شب منتشر میشود، CDN در ابتدای کار هیچ فایلی از آن را در کش ندارد. میلیونها درخواست در یک دقیقه وارد میشوند؛ همه آنها Cache Miss میشوند و به صورت همزمان به سمت سرور اصلی (Origin) هجوم میبرند (مشکلی که در بکاند به آن Thundering Herd Problem میگویند).
نتیجه؟ سیستم دقیقاً در لحظهای که بیشترین بیننده را دارد، شدیدترین لودینگ را تجربه میکند! نتفلیکس برای حل این مشکل، صورت مسئله را کلاً دور زد.
مکانیزم اول: فیلم از قبل در همسایگی شماست! (Open Connect)
نتفلیکس شبکه تحویل محتوای اختصاصی خود به نام Open Connect را ساخت. بخش عجیب و شگفتانگیز این سیستم، سختافزاری بودن آن است.
نتفلیکس سرورهای فیزیکی واقعی به نام Open Connect Appliances (OCA) را به طور مستقیم و کاملاً رایگان درون دیتاسنترهای ارائه دهندگان اینترنت (ISPها) و مراکز تبادل اینترنت (IXP) نصب میکند. طبق آمار رسمی، این شبکه بیش از ۱۷,۰۰۰ سرور را در ۱۵۸ کشور پوشش داده است.
چرا ISPها این سرورها را مجانی قبول میکنند؟
چون هر بایتی که از داخل شبکه خود ISP سرو شود، بایتی است که آنها مجبور نیستند برای انتقالش در پهنای باند بینالمللی و ترانزیت پول بپردازند. یک معامله دو سر برد واقعی!
جادوی کشینگ پیشفرض (Nightly Fill Window)
هر باکس OCA شامل بخشی از آرشیو نتفلیکس است که احتمال تماشای آن در آن منطقه بیشتر است. اما نکته کلیدی اینجاست: این سرورها از قبل پر میشوند!
هر شب، در ساعات خلوت شبانه (مثلاً ۳ تا ۶ صبح)، الگوریتمهای هوش مصنوعی نتفلیکس میزان تقاضای فردای هر منطقه را پیشبینی کرده و فایلهای ویدیویی لازم را روی سرورهای OCA همان منطقه کپی میکنند. بنابراین سریالی که قرار است جمعه شب منتشر شود، عصر پنجشنبه روی سروری درست داخل ساختمان ارائه دهنده اینترنت شما قرار گرفته است!
[ گوشی / TV شما ] │ ├──── (۱) درخواست کمحجم API ─────────────► [ AWS Cloud ] │ │ │ │ دریافت Manifest (URL) │ │ └──── (۲) دانلود ویدیوی سنگین ────────────► [ سرور OCA داخل ISP شما ]
جداسازی هوشمندانه: Control Plane در برابر Data Plane
وقتی دکمه Play را میزنید، دو مسیر کاملاً متفاوت طی میشود:
فیلم هرگز از ابر (Cloud) نمیآید! نتفلیکس کنترلپلاین را جایی گذاشته که انعطافپذیری ارزان است (AWS) و دیتاپلاین را جایی گذاشته که بایتها حضور دارند (Open Connect).
مکانیزم دوم: تلویزیون شما در حین پخش، کیفیت را مذاکره میکند (ABR)
پیشبینی شبانه اینترنت کشور را نجات میدهد، اما مشکلی برای Wi-Fi شلوغ خانه شما، مایکروویو یا دانلود همزمان اعضای خانواده حل نمیکند! این بخش بر عهده کلاینت (App/TV) است.
نردبان کیفیت اختصاصی (Per-Title Encoding Ladder)
هر فیلم یا سریال قبل از انتشار، به یک "نردبان کیفیت" با بیتریتهای مختلف (از ۲۳۵Kbps تا ۱۵Mbps برای 4K) تبدیل میشود. این نردبان به صورت اختصاصی برای هر محتوا ساخته میشود؛ مثلاً یک انیمیشن دوبعدی بیتریت بسیار کمتری نسبت به یک فیلم اکشن پرنویز نیاز دارد.
پخشکننده مبتنی بر بافر (Buffer-based ABR)
ویدیو به قطعات کوچک چند ثانیهای (Chunks) تقسیم میشود. اپلیکیشن نتفلیکس هنگام دانلود هر قطعه:
اگر پهنای باند شما افت کند، سیستم قبل از خالی شدن بافر، قطعه بعدی را با کیفیت پایینتر دانلود میکند. نتیجه؟ تصویر برای چند ثانیه کمی تار میشود، اما هرگز چرخنده لودینگ (Spinner) را نمیبینید!
همچنین نتفلیکس با به کارگیری کدک پیشرفته AV1 باعث شده با همان کیفیت تصویر، پهنای باند کمتری مصرف شود.
اصل طلایی معماری: درخواست، آخرین مرحله است نه اولین!
ما برنامهنویسها عادت کردهایم درخواست کاربر را شروع کار بدانیم: درخواست میرسد -> سیستم پردازش میکند -> پاسخ داده میشود.
اما معماری نتفلیکس دقیقاً برعکس کار میکند: وقتی شما دکمه Play را میزنید، فایل ویدیو دیشب انتخاب شده، ماهها قبل انکود شده و ساعاتی قبل روی سرور محلی ISP شما کپی شده است. کلیک شما تقریباً هیچ پردازش سنگینی ایجاد نمیکند؛ فقط یک فراخوانی کوچک API، یک فایل Manifest و سپس یک انتقال دیتای محلی!
در این مقیاس، واکنش نشان دادن به تقاضای کاربر یعنی شما از قبل دیر کردهاید!
چطور این الگو را در پروژههای خودمان (در مقیاس ۱/۱۰۰۰) پیاده کنیم؟
نیازی نیست ۱۷,۰۰۰ سرور داشته باشید تا از این اصول استفاده کنید. چه بکاند دولوپر باشید، چه جونیور یا فولاستک، این ۳ درس را در کدنویسی رعایت کنید:
۱. گرم کردن کشها (Cache Pre-warming) هنگام Deploy
اگر قرار است قابلیتی را برای ۵۰,۰۰۰ کاربر منتشر کنید، موقع دپلوپ کشها و CDN را با اسکریپت پیشفرض پر (Warm) کنید تا اولین کاربران سایت تاوان Cache Miss را ندهند.
۲. محاسبه قبل از درخواست (Pre-computation)
در داشبوردهای سنگین یا گزارشگیریهای پرمصرف، به جای اجرای کوئریهای سنگین SQL (COUNT, SUM, JOIN) در هر درخواست کاربر، آمارها را با Cron Job یا Queue در پسزمینه محاسبه کرده و نتیجه آماده را در Redis ذخیره کنید.
۳. تنزل درجه محترمانه (Graceful Degradation)
برای شرایطی که اینترنت کاربر ضعیف است، در فرانتاند یا موبایل استراتژیهای هوشمند داشته باشید:
💬 نظر شما چیست؟
به نظرتان این معماری در چه نقطهای ممکن است شکست بخورد؟ آیا شما هم در پروژههاتون از تکنیکهای Pre-computation استفاده کردید؟ خوشحال میشم نظرتون رو توی کامنتهای DevShayan.ir بنویسید تا با هم گپ بزنیم!
Nice!