الأساسيات · فصل ١

السيستم الكويس: يستحمل، يكبر، ويتصان

Reliable, Scalable and Maintainable Applications
🎯 الهدف: تتكلم بلغة الكتاب: تفرق بين fault و failure، تقيس الأداء بالـ percentiles، وتوصف الحمل بأرقام.

يعني إيه أبلكيشن Data-Intensive؟

معظم الأبلكيشنز النهارده مش مشكلتها إن الـ CPU مش ملاحق (compute-intensive)، مشكلتها في الداتا نفسها: حجمها، تعقيدها، وسرعة تغيّرها. ده اللي الكتاب بيسميه data-intensive.

والأبلكيشن العادي بيتبني من “طوب جاهز” بيتكرر في كل حتة:

Database — تخزين واسترجاعCache — تسريع القراءات التقيلةSearch Index — بحث وفلترةStream Processing — رسايل asyncBatch Processing — تقطيع داتا كبيرة دوريًا

الكتاب بيركز على 3 هموم أساسية:

Reliability — الاعتمادية

ببساطة: السيستم يفضل شغال صح حتى لما الحاجات تبوظ. يعني يعمل اللي المستخدم متوقعه، يستحمل غلطات المستخدم، أداءه مقبول، ويمنع الاستخدام الغلط أو الاختراق.

Fault (عطل)

جزء واحد من السيستم خرج عن المواصفات (هارد مات، سيرفر وقع).

Failure (انهيار)

السيستم ككل بطّل يقدّم الخدمة للمستخدم.

الهدف إنك تبني fault-tolerant سيستم: مش هتمنع الـ faults (مستحيل)، بس تمنعها تتحول لـ failure. وفيه شركات بتعطّل حاجات عمدًا عشان تتأكد إن آليات الحماية شغالة (زي Chaos Monkey بتاع Netflix).

أنواع الأعطال التلاتة

النوعشكلهبنتعامل معاه إزاي
🖥️ Hardwareهاردات بتموت (متوسط عمر الهارد 10–50 سنة، فلو عندك 10 آلاف هارد توقّع هارد يموت كل يوم تقريبًا)، رامات، كهربا. الأعطال دي عشوائية ومش مرتبطة ببعض.Redundancy: RAID، باور مزدوج، مولدات. ومع الكلاود بقينا نصمم السوفتوير نفسه يستحمل إن ماكينة كاملة تختفي (وده بيسهل كمان الـ rolling upgrades).
🐛 Softwareأخطر: مترابطة (systematic) — باج واحد يوقع كل السيرفرات مرة واحدة (زي باج الـ leap second 2012)، process بياكل كل الرام، خدمة تانية بتبطّأ، cascading failures.مفيش حل سحري: تفكير كويس في الافتراضات، تست، عزل الـ processes، إنك تسيب الـ process يقع ويقوم تاني، مونيتورينج ومقارنة الـ invariants وقت التشغيل.
🙋 Humanالبشر هم السبب الأكبر — أخطاء الـ configuration من الأوبريترز كانت أكتر من أعطال الهاردوير في دراسة على خدمات إنترنت كبيرة.APIs تصعّب الغلط، sandbox للتجربة، تست شامل (unit + integration + manual)، rollback سريع ونشر تدريجي، مونيتورينج واضح (telemetry)، وتدريب كويس.

Scalability — القابلية للتوسع

“السيستم ده scalable” جملة فاضية! السؤال الصح: لو الحمل زاد بالطريقة الفلانية، إيه خياراتنا عشان نلاحق؟

أولًا: وصف الحمل (Load Parameters)

لازم تحدد الأرقام اللي تمثل الحمل عندك: requests/sec، نسبة القراءة للكتابة، عدد المستخدمين الأونلاين، الـ cache hit rate… وأحيانًا المهم هو المتوسط وأحيانًا الحالات المتطرفة.

ثانيًا: وصف الأداء

Batch (زي Hadoop)

بيهمنا الـ Throughput: كام ريكورد في الثانية، أو الجوب ياخد وقت قد إيه.

Online services

بيهمنا الـ Response time: من لحظة الطلب لحد الرد.

Latency ≠ Response time: الـ response time هو اللي العميل شايفه (خدمة + شبكة + طوابير)، والـ latency هو الوقت اللي الريكوست قاعد مستني فيه يتخدم.

الـ response time مش رقم واحد، ده توزيع (distribution). وفيه outliers بسبب GC pause، باكت ضاع واتبعت تاني، context switch…

المصطلحات دي بتدخل في الـ SLO وSLA: مثلًا “الخدمة متاحة لو الميديان أقل من 200ms والـ p99 أقل من ثانية”.

ثالثًا: إزاي نتعامل مع الحمل

⬆️ Scale Up (vertical)

ماكينة أقوى. بسيط، بس غالي جدًا ومحدود.

➡️ Scale Out (horizontal)

ماكينات صغيرة كتير = shared-nothing. أرخص بس بيدخل تعقيد الأنظمة الموزعة.

  • Elastic (بيزود موارد أوتوماتيك) مفيد لو الحمل مش متوقع، واليدوي أبسط وأقل مفاجآت.
  • الـ stateless services سهل توزعها، لكن الداتابيز (stateful) توزيعها صعب جدًا — عشان كده لحد قريب كانت النصيحة: خليها على ماكينة واحدة لحد ما تتزنق.
  • مفيش “magic scaling sauce”: المعمارية الصح متفصّلة على الحمل بتاعك. سيستم بيعمل 100 ألف ريكوست/ث كل واحد 1KB مختلف تمامًا عن سيستم بيعمل 3 ريكوستات/دقيقة كل واحد 2GB، مع إن الاتنين نفس الـ throughput!
  • في بداية الستارت أب: الأهم إنك تتحرك بسرعة في الفيتشرز مش إنك تصمم لحمل افتراضي.

Maintainability — سهولة الصيانة

أغلب تكلفة السوفتوير مش في كتابته، في صيانته المستمرة (باجات، تشغيل، migrations، فيتشرز جديدة). ومحدش بيحب يشتغل على legacy. فبنصمم من الأول على 3 مبادئ:

المبدأيعني إيهعمليًا
⚙️ Operabilityفريق التشغيل يقدر يشغّله بسهولة.مونيتورينج كويس، أوتوميشن، مايبقاش معتمد على ماكينة واحدة، documentation، default behavior معقول مع إمكانية override، سلوك متوقع (no surprises).
🧩 Simplicityمهندس جديد يفهم السيستم.إزالة الـ accidental complexity (التعقيد اللي جاي من التنفيذ مش من المشكلة نفسها). أهم سلاح: Abstraction كويس (زي SQL اللي بتخبي تفاصيل الهارد والـ concurrency).
🔄 Evolvabilityسهولة التغيير لما المتطلبات تتغير.Agile و TDD و refactoring — والكتاب بيبص لها على مستوى الـ data systems كلها، مش مجرد كود صغير.

🧪 Lab

  1. افتح أي API عندك (الـ backend بتاع شغلك أو مشروع جانبي) واعمل load test بسيط بـ k6 أو autocannon.
  2. سجّل p50 و p95 و p99 مش المتوسط بس — لاحظ الفرق بينهم.
  3. ضيف endpoint بينادي 3 خدمات/queries ورا بعض، وشوف الـ p99 بيزيد قد إيه (tail latency amplification).
  4. اكتب في سطرين: إيه الـ load parameters الأهم في السيستم ده؟
npx autocannon -c 50 -d 20 http://localhost:3000/api/jobs

✅ الخلاصة — Checklist

🧠 اختبر نفسك
١) ليه الـ software bugs أخطر من أعطال الهاردوير؟
لأنها مترابطة: نفس الباج بيضرب كل النودز في نفس الوقت، مش عشوائي ومستقل.
٢) p99 = 2s معناها إيه؟
99% من الريكوستات أسرع من 2 ثانية، و1% أبطأ.
٣) إمتى الـ fan-out on write يبقى وحش؟
لما حد عنده ملايين المتابعين — بوست واحد يبقى ملايين كتابات.