عملية تصميم الأنظمة
عملية تصميم الأنظمة
لا يجلس المهندسون ذوو الخبرة ليبدأوا فوراً برسم قواعد البيانات أو اختيار التقنيات. بل يتبعون عملية منظمة وقابلة للتكرار تحوّل وصف المشكلة الغامض — "صمّم تويتر" أو "ابنِ منصة مشاركة الرحلات" — إلى معمارية محددة وقابلة للدفاع. يعلمك هذا الدرس تلك العملية خطوة بخطوة، حتى تتمكن من تطبيقها في المقابلات ومراجعات التصميم والمشاريع الحقيقية.
العملية من خمس مراحل
كل جلسة تصميم نظام — سواء كانت مقابلة مدتها 45 دقيقة أو مراجعة معمارية تستغرق ثلاثة أسابيع — تقوم على المراحل الخمس ذاتها:
- جمع المتطلبات وتوضيحها
- تقدير الحجم والطاقة
- إنتاج تصميم رفيع المستوى
- التعمق في المكونات الحرجة
- تحديد نقاط الاختناق ومعالجتها
هذه المراحل تكرارية وليست خطية بالضرورة. قد يكشف التعمق في مكوّن معين عن حاجة لمراجعة تقديراتك. وقد تفرض عليك نقطة اختناق إعادة النظر في التصميم الكلي. فكّر في هذه المراحل كحلقة تبدأ دائماً من نقطة ثابتة.
المرحلة الأولى — جمع المتطلبات وتوضيحها
قبل أن ترسم أي مكوّن، خصّص وقتاً لطرح الأسئلة. تنقسم المتطلبات إلى فئتين:
- المتطلبات الوظيفية — ما الذي يفعله النظام. مثال لمختصر روابط: يلصق المستخدم رابطاً طويلاً ويحصل على رابط قصير؛ وعند زيارة الرابط القصير يُعاد توجيهه إلى الأصل.
- المتطلبات غير الوظيفية — مدى جودة أداء النظام. هدف التوفر (99.9% مقابل 99.99%)، زمن الاستجابة المقبول للقراءة (أقل من 100 مللي ثانية)، ضمانات الاستدامة، التوزيع الجغرافي، والقيود التنظيمية.
أسئلة جيدة لطرحها: من هم المستخدمون وكيف يتفاعلون مع النظام؟ ما معيار النجاح؟ ما نسبة القراءة إلى الكتابة؟ هل يجب أن تكون البيانات متينة؟ ما النمو المتوقع خلال السنة أو السنتين القادمتين؟
المرحلة الثانية — تقدير الحجم والطاقة
المتطلبات تمنحك الماذا؛ والتقدير يمنحك الكم والحجم. تحتاج إلى أرقام تقريبية لاتخاذ قرارات تقنية سليمة. حسابات التقدير السريع — التي يتناولها الدرس الرابع بتعمق — تغطي ثلاثة محاور:
- حركة المرور: كم طلباً في الثانية؟ (مثلاً: 100 مليون مستخدم نشط يومياً × 10 طلبات/يوم = ~11,600 طلب/ثانية)
- التخزين: كم من البيانات ستتراكم؟ (مثلاً: 100 مليار سجل × 500 بايت في المتوسط = 50 تيرابايت)
- عرض النطاق الترددي: ما الإنتاجية القصوى للبيانات الواردة والصادرة؟ هل يخدم النظام ملفات وسائط ضخمة أم حمولات JSON صغيرة؟
هذه الأرقام تحدد ما إذا كنت تحتاج قاعدة بيانات واحدة أم مجموعة موزعة، وما إذا كنت بحاجة إلى CDN، وما إذا كانت ذاكرة التخزين المؤقت العادية كافية أم تحتاج طبقة Redis مخصصة.
المرحلة الثالثة — التصميم رفيع المستوى
بعد تحديد المتطلبات والحجم، ارسم المكونات الرئيسية وكيف تتدفق البيانات بينها. يُظهر التصميم رفيع المستوى عادةً: العملاء، موازنات الحمل، خوادم التطبيقات، الذاكرات المؤقتة، قواعد البيانات، طوابير الرسائل، والخدمات الخارجية. لم تحدد بعد منتج قاعدة البيانات المحدد أو كيفية تشظيته — ذلك يأتي لاحقاً.
هدف هذه المرحلة بناء نموذج ذهني مشترك يستطيع الجميع التفكير فيه بوضوح. احرص على بساطته بحيث يسع لوحة بيضاء واحدة.
المرحلة الرابعة — التعمق في المكونات الحرجة
اختر المكونين أو الثلاثة التي تحمل أعلى مخاطرة تقنية وادرسها بعمق. لكل مكوّن يجب أن تجيب على:
- نموذج البيانات: كيف يبدو المخطط؟ كيف يُقسَّم الداتا؟
- عقد الواجهة البرمجية: ما توقيعات نقاط النهاية الرئيسية والحمولات؟
- الخوارزمية أو البروتوكول: كيف يؤدي المكوّن وظيفته فعلياً؟ (مثلاً: Consistent Hashing لطبقة الكاش، أو Snowflake IDs لتوليد المفاتيح في مختصر الروابط)
- أوضاع الفشل: ماذا يحدث عندما يكون هذا المكوّن بطيئاً أو غير متاح؟
وجّه تعمقك نحو ما أبدى المحاور أو الفريق اهتماماً به. في مختصر الروابط، يكون ذلك عادةً توليد المفاتيح (ضمان التفرد على نطاق واسع) ومسار إعادة التوجيه الساخن (هدف كمون أقل من 10 مللي ثانية).
المرحلة الخامسة — تحديد نقاط الاختناق ومعالجتها
لا يوجد تصميم مثالي. في المرحلة الأخيرة، اختبر معماريتك بضغط من خلال طرح هذه الأسئلة:
- ما نقطة الفشل الوحيدة (SPOF)؟ كيف تزيلها؟ (مثلاً: أضف موازن حمل احتياطياً، استخدم الفشل الانتقالي للمقاطع الأولية والمتماثلة)
- ماذا يحدث عندما ينمو حجم حركة المرور 10 أضعاف بين عشية وضحاها؟ أي مكوّن يتعطل أولاً؟
- هل هناك نقاط ساخنة؟ (مثلاً: مقطع واحد يستقبل حركة مرور غير متناسبة بسبب مستخدم مشهور)
- هل هناك خطر قطيع الرعد عندما تكون ذاكرة التخزين المؤقت فارغة بعد إعادة التشغيل؟
لكل نقطة اختناق، اقترح معالجة محددة: التوسع الأفقي، التخزين المؤقت في طبقة أعلى، طوابير الرسائل لاستيعاب أعباء حركة المرور المتقاطرة، قواطع الدائرة لعزل الأعطال، أو التشظي الجغرافي لتقليص الكمون للمستخدمين الدوليين.
تطبيق عملي: مثال متكامل
تخيّل أنك تصمم لوحة قيادة فورية لأفضل اللاعبين في لعبة جوالة تضم 50 مليون مستخدم نشط يومياً. تتكشف المراحل الخمس كالتالي:
- المتطلبات: عرض أفضل 100 لاعع عالمياً؛ تحديث النتائج خلال ثانيتين؛ النظام ثقيل القراءة (نسبة 100:1 قراءة/كتابة).
- التقدير: 50 مليون مستخدم × 20 تحديث نتيجة/يوم = ~11,500 كتابة/ثانية؛ نسبة 100:1 = ~1.15 مليون قراءة/ثانية في الذروة.
- التصميم الكلي: خدمة استقبال النتائج ← طابور الرسائل ← عمال التجميع ← مجموعة Redis المرتبة ← خوادم API ← العملاء.
- التعمق:
ZADDوZRANGEفي Redis على مجموعة مرتبة واحدة؛ تشظٍّ حسب المنطقة إن تمت التضحية بالاتساق العالمي؛ TTL على المدخلات القديمة. - نقاط الاختناق: نقطة الفشل الوحيدة في مجموعة Redis — أضف نسخاً متماثلة وـsentinel؛ خطر المفتاح الساخن للوحة العالمية — فكّر في تقريب أفضل K باستخدام Count-Min Sketch.
لاحظ كيف تغذّي كل مرحلة التالية، وكيف يرتكز النظام النهائي بثبات على المتطلبات التي حُددت في البداية. هذه هي قوة العملية القابلة للتكرار.