الأحمال الثقيلة وبروفتك
صمّم منصة فيديو
ارفع فيديو، واضغط تشغيل في مكان آخر، فيعمل كل شيء. خلف هذه الجملة يقف نظامان من أكثر الأنظمة تعليماً سترسمهما في حياتك: مصنع مدفوع بالطوابير يحوّل ملفاً خاماً واحداً إلى عشرات الملفات القابلة للبث، وشبكة توصيل تخدم بيتابايتات يومياً دون أن تلمس خوادمك. صمّم كليهما، وقد صمّمت النصف الصعب من الإنترنت الحديث.
قلها في الدقيقة الأولى من المقابلة: منصة الفيديو مساران. مسار الرفع — يرفع صانع محتوى ملفاً خاماً، فتلتهمه المنظومة وتحوّله (transcode) إلى كل دقة سيُشاهَد بها يوماً. ومسار التشغيل — يضغط المشاهد زر التشغيل، فتتدفق مقاطع صغيرة من الفيديو إلى جهازه بالجودة التي يحتملها اتصاله في هذه اللحظة. المساران يتشاركان التخزين ولا شيء تقريباً غيره؛ يتوسّعان ويفشلان كلٌّ على حدة. أرقام للظرف: 500 ساعة مرفوعة في الدقيقة، ونسبة مشاهدة إلى رفع 10:1، وفيديو واحد منتهٍ يصبح 6–10 ملفات ناتجة.
ساعة واحدة من لقطات 4K الخام قد تبلغ 50 GB. لن ترسلها في طلب POST واحد. يقسّم العميل الملف إلى مقاطع — 8 MB مثلاً — ويرفعها إلى object storage متتبعاً أرقام المقاطع التي نجحت. الاتصال المنقطع يستأنف المقطع، لا الملف: أعد محاولة المقطع رقم 4,217، لا الخمسين غيغابايت. وعند وصول آخر مقطع، ينطلق حدث اكتمال، ويصبح لدى مخزن الكائنات نسخة أصلية واحدة غير قابلة للتعديل. هذه أيضاً قصة متانتك — فـobject storage يكرّر البيانات عبر الأجهزة نيابة عنك، فينجو الأصل الخام من أعطال الأقراص دون أن تكتب أنت ذلك الكود.
حدث الاكتمال يُسقط رسالة في queue، وتنهش مجموعة من الـworkers شجرة DAG: قسّم الأصل إلى مقاطع ← حوّل كل مقطع إلى 1080p و720p و480p و360p على التوازي، لكل منها ترميزها (codec) ← ادمج النتائج واكتب ملفات الـmanifest. لماذا DAG وليس سكربت متسلسل؟ توازٍ حيث العمل مستقل — كل زوج (مقطع، دقة) مهمة مستقلة على worker مستقل — وتسلسل حيث العمل مترابط — الدمج لا يبدأ حتى تنتهي كل عمليات التحويل لتلك الدقة. ولماذا queue وليس استدعاء متزامناً؟ لأن التحويل يستغرق دقائق إلى ساعات؛ الرافع لا يجب أن ينتظر، والـworkers يجب أن تُعيد المحاولة إن ماتت في منتصف مقطع، والـqueue يمتص ذروة الرفع في الثامنة مساءً بدلاً من ميزانية معالجاتك.
المشغّل لا يحمّل «فيديو» أبداً. يجلب ملف manifest — ملفاً نصياً صغيراً يسرد كل دقة كتسلسل من مقاطع طولها 2–6 ثوانٍ — ثم يحمّل مقطعاً مقطعاً، قاسياً سرعة النقل عند كل واحد. انخفض عرض الحزمة؟ يُطلب المقطع التالي بدقة 480p. تعافى؟ يعود إلى 1080p، في منتصف الفيديو، في منتصف المشهد. منطق التكيّف يسكن كله في العميل؛ أما الخوادم فآلات بيع مقاطع غبية. هذه هي خدعة adaptive bitrate streaming كلها: ضع الذكاء حيث يوجد القياس.
الفيديو الشائع يخضع لقانون قوة قاسٍ: جزء صغير من المحتوى يستأثر بالغالبية الساحقة من وقت المشاهدة. ذلك الجزء يعيش عند حافة الـCDN، في نقاط حضور قريبة من المشاهد. الحافة الساخنة تخدم المقطع دون أن تناديك أبداً — الـorigin لا يرى إلا شيئين: غيابات الـcache عن المحتوى البارد أو الجديد كلياً، والرفعات الأصلية القادمة من خط التحويل. إذن صمّم الـorigin للغيابات لا لمجموع الحركة؛ نظام مصمم ليخدم كل تشغيل من الـorigin سيحتاج مئة ضعف من الـegress، وسيبقى أبطأ، لأن الفيزياء تحاسبك على المسافة.
مخزن الكائنات يكلّف سنتات للغيغابايت في الشهر — مكتبة من عشرة ملايين فيديو مجرد هامش في المحاسبة. أما عرض الحزمة فيكلّف دولارات للغيغابايت المُسلَّم، ويتوسّع مع النجاح: كل ساعة مشاهدة تدفع العداد من جديد. لهذا الـCDN ليس تحسيناً اختيارياً، بل هو نموذج العمل نفسه. والـmetadata — العنوان والمالك والمدة وملفات manifest لمقاطع كل دقة — تسكن في مخزن علائقي قوي الاتساق: هي ضئيلة بجانب الكتل الثنائية، وتُستعلم استعلاماً علائقياً (فيديوهات مالك ما، أو الأحدث)، وهي الشيء الوحيد الذي لا تحتمل فقدانه أو خدمته قديماً.
منصة الفيديو نظامان يتقاسمان فاتورة تخزين: مصنع غير متزامن يحوّل الرفعات إلى منتجات قابلة للبث بوتيرته الخاصة، وشبكة توصيل شبه مقروءة بالكامل تخدم تلك المنتجات من الحافة. ما إن ترى هذا الانقسام، ينتظم كل قرار في مكانه — الطوابير وإعادات المحاولة وشجرات DAG في جانب المصنع؛ والتخزين المؤقت والتوزيع الجغرافي واقتصاديات عرض الحزمة في جانب التوصيل.
مات رفع أحد صنّاع المحتوى عند 92% على شبكة فندق. ما الذي يُعاد بالضبط، ولماذا لا يتعطّل خط الـtranscode في كلتا الحالتين؟ (تُستأنف المقاطع الفاشلة فقط — تتبّع الرفع على مستوى المقطع في object storage يعني أن الـ92% محفوظة؛ والخط لا يتعطّل أصلاً لأن الـqueue يفصل الرفع عن التحويل — شجرة DAG تبدأ عند انطلاق حدث الاكتمال، وفق جدول المنصة، لا وفق اتصال صانع المحتوى.)
ارسمها في صندوقين وقد سبقت معظم إجابات السبورة: رفع مقسّم قابل للاستئناف إلى object storage، وشجرة transcoding تغذيها queue، ومشغّل متكيّف يقوده manifest، وCDN يحوّل الـorigin إلى معالج غيابات. التخزين رخيص، وعرض الحزمة هو الفاتورة، والـmetadata — الصغيرة العلائقية الثمينة — هي الجزء الوحيد الذي يحتاج قاعدة بيانات حقيقية.
خذ ملفاً كبيراً ينقله نظامك اليوم — استيراد CSV أو تقريراً أو نسخة احتياطية — واجعل نقله مقسّماً وقابلاً للاستئناف: أجزاء ثابتة الحجم، وسجل بأرقام الأجزاء المكتملة، واستئناف من أول جزء مفقود. ثم دوّن، في جملة واحدة لكل منها، أيّ مهامك المتزامنة الحالية ستصبح شجرة DAG تغذيها queue لو تضخمت مئة ضعف.
الأحمال الثقيلة وبروفتك