الأحمال الثقيلة وبروفتك
صمّم خدمة مزامنة ملفات
تحفظ فيديو بحجم 1 GB على حاسوبك المحمول، وبعد ثلاثين ثانية يكون على هاتفك. المحرّر لم يلمس سوى 10 MB منه. في مكان ما، قرّر نظامٌ ما نقل 12 MB بدلاً من 1 GB — وهذا القرار هو التصميم كله. كل ما عداه محض قيود وحسابات.
لا تُزامن الملفات — زامن الكتل (blocks). قسّم كل ملف إلى قطع ثابتة الحجم (4 MB مثلاً) واحسب hash لكل قطعة. الآن الكتلة التي لم تتغير لن تُرفع مرة أخرى، لأن الـhash الخاص بها موجود أصلاً على الخادم. والكتلة المتطابقة التي تظهر في مئة ملف تُخزَّن مرة واحدة فقط، لأن الـhash هو عنوانها. هذا القرار المفرد — التقطيع والـhashing — هو الذي يحدد فاتورة النطاق الترددي وفاتورة التخزين وسرعة المزامنة في النظام بأكمله.
ملف بحجم 1 GB مع كتل من 4 MB يعني 250 كتلة — أي 250 قيمة hash، بضعة كيلوبايتات من metadata. عدّل 10 MB في المنتصف: تتغير 3 كتل كحد أقصى، فيرفع العميل ~12 MB مع قائمة الـhashes الجديدة، لا 1 GB كاملاً. وعلى جانب التخزين: إذا احتفظ 10,000 مستخدم بنسخة من الملف نفسه، فإزالة التكرار (dedup) تخزّنه مرة واحدة لا 10,000 مرة. التخزين المُعنون بالمحتوى (content-addressed storage) يحوّل التكرار إلى عدّاد، لا إلى نسخة.
- خدمة metadata: اسم الملف ← قائمة مرتبة من قيم hash الكتل، والإصدارات، والصلاحيات، والمشاركة. صغيرة وساخنة ويجب أن تكون صحيحة دائماً — ضعها على مخزن علائقي متسق بقوة (strongly consistent).
- مخزن الكتل: البايتات الفعلية، مُعنونة بالـhash. ضخمة وباردة وغير قابلة للتعديل — ضعها في object storage رخيص، حيث يكلف التيرابايت جزءاً يسيراً مما تكلفه قاعدة البيانات.
- لماذا الفصل بينهما؟ الـmetadata كيلوبايتات قليلة لكل ملف لكنها تحتاج معاملات (transactions) واتساقاً — قائمة كتل خاطئة تعني ملفاً تالفاً. أما الـblobs فجيجابايتات لا تحتاج سوى المتانة — فالـhash وحده يضمن السلامة. إسكان كل منهما في أرخص مكان صحيح له هو نموذج التكلفة بأكمله.
- الدفع (push): مراقب على جهاز العميل يلتقط التغييرات المحلية، يعيد تقطيع الملفات المتغيرة، يقارن الـhashes بالقائمة المعروفة سابقاً، ويرفع فقط الكتل التي ينقصها الخادم.
- السحب (pull): يسأل العميل خدمة metadata عمّا تغير منذ آخر مزامنة، ينزّل الكتل الناقصة، ويعيد تركيب الملفات محلياً.
- الإشعار: تعرف أجهزة المستخدم الأخرى بالتغييرات عبر long polling أو push notifications — الرسالة لا تحمل بيانات، مجرد «شيء ما تغيّر، تعالَ واسحب». رخيصة وقابلة للتوسع لأن العمل الثقيل يبقى كله في السحب.
الأولوية للكتابة الأخيرة (last-write-wins) على مستوى الملف: التعديل الأحدث يصبح النسخة الحالية. يبدو قاسياً، لكن لا شيء يُفقد بصمت — سجل الإصدارات يحتفظ بالخاسر، فيستطيع المستخدم استعادته. دمج تعديلين متزامنين على مستوى الكتل مشروع بحثي؛ أما last-write-wins على مستوى الملف مع سجل إصدارات فمنتج حقيقي. اختر ما تستطيع شحنه والدفاع عنه.
الحواسيب المحمولة تُغلق في منتصف التعديل، والهواتف تفقد الإشارة في المصاعد. التعديلات التي تتم دون اتصال تصطف محلياً في queue — العميل يواصل التقطيع والـhashing كالمعتاد، وعند عودة الاتصال يعيد تشغيل الطابور: يرفع الكتل الناقصة، يثبّت الـmetadata الجديدة، ويحلّ أي تعارض مع إصدارات وصلت أثناء غيابه. المستخدم لا يرى فرقاً بين «حُفظ» و«زُومن» حتى يبحث عنه.
المزامنة مشكلة metadata تركب فوق مشكلة blobs. الـblobs سهلة ما إن تصبح مُعنونة بالمحتوى: إزالة التكرار والسلامة ورفع الفروقات كلها تسقط هبةً من الـhash. كل ما يجادل فيه البشر — الإصدارات والتعارضات والمشاركة والعمل دون اتصال — يسكن في بضعة كيلوبايتات من metadata لكل ملف. أتقِن الـhashes وكل ما عداها يصبح قيوداً دفترية.
فيديو بحجم 1 GB عُدِّل منه 10 MB — ما الذي يعبر الشبكة فعلاً، ولماذا؟ (مع كتل من 4 MB، يمسّ التعديل 3 كتل كحد أقصى؛ يعيد العميل حساب الـhashes للملف، فيجد أن هذه الكتل وحدها هي الناقصة على الخادم، فيرفع ~12 MB مع تثبيت metadata صغير — بضعة كيلوبايتات. أما الـ247 كتلة الباقية فلا تتحرك، لأن الـhashes الخاصة بها متطابقة أصلاً.)
إجابة المقابلة في نفَس واحد: قطّع الملفات واحسب hash للكتل وأزِل التكرار من التخزين؛ الـmetadata في مخزن علائقي متسق، والبايتات في object storage رخيص؛ العملاء يدفعون الفروقات ويسحبون عند الإشعار؛ الأسبقية للكتابة الأخيرة مع سجل إصدارات؛ وتعديلات الانقطاع تصطف ثم تُعاد. كل قطعة تستمد مبررها من القرار الأول.
خذ أي ملف كبير عدّلته مؤخراً وقدّر كلفة مزامنته بالطريقتين: رفع الملف كاملاً مقابل كتل من 4 MB. اكتب سكربت صغيراً يقطّع الملف ويحسب hash لكل كتلة (SHA-256) ويعدّ كم قيمة hash تتغير بين نسختين — ثم قارن البايتات التي كانت ستتحرك. لن تصمّم مزامنة ملفات بالطريقة الساذجة مرة أخرى.
الأحمال الثقيلة وبروفتك