الفكرة الكبيرة في كلمتين
الفصل ده ماشي بمنطق ابدأ صغير وكبّر لما تتزنق. بنبدأ بسيستم كله على سيرفر واحد، وكل ما عدد اليوزرز يزيد بنقابل مشكلة، فنضيف قطعة جديدة تحلها. في الآخر بيبقى عندك علبة أدوات.
البداية: سيرفر واحد شايل كل حاجة
في الأول، الـ web app والداتابيز والكاش كلهم قاعدين على ماكينة واحدة. زي محل كشري صغير: نفس الراجل بياخد الأوردر ويطبخ ويحاسب.
- اليوزر بيكتب الدومين، والـ DNS (غالبًا خدمة خارجية) بيترجمه لـ IP — زي دليل التليفونات.
- البراوزر أو الموبايل بياخد الـ IP ويبعت HTTP request للسيرفر على طول.
- السيرفر بيرد بـ HTML لو ويب، أو JSON لو API للموبايل.
أول فصل: الداتابيز في سيرفر لوحدها
أول ما اليوزرز يزيدوا، بنفصل سيرفر الويب عن سيرفر الداتا. المزية إن كل واحد فيهم يكبر لوحده.
| النوع | أمثلة | إمتى تختاره؟ |
|---|---|---|
| Relational (SQL) | PostgreSQL, MySQL, Oracle | الاختيار الافتراضي: جداول وعلاقات و JOIN، ومستقر من عشرات السنين |
| Non-Relational (NoSQL) | Cassandra, DynamoDB, MongoDB, Neo4j | latency قليلة جدًا، أو الداتا مش متهيكلة، أو كمية مهولة، أو بس بتعمل serialize لـ JSON |
تكبير لفوق ولا تكبير بالعرض؟
تزوّد CPU و RAM لنفس الماكينة. زي ما تكبّر المطبخ بدل ما تفتح فرع.
- بسيط جدًا لما الترافيك قليل.
- ليه سقف: مفيش ماكينة بتكبر للنهاية.
- لو وقعت، كله وقع.
تضيف سيرفرات أكتر جنب بعض. زي ما تفتح فروع.
- مفيش سقف تقريبًا.
- لو سيرفر وقع، الباقي شغال.
- ده اللي بيتعمل في الـ large-scale systems.
الـ Load Balancer: عسكري المرور
بيقف قدام السيرفرات ويوزّع الترافيك عليهم. اليوزر بيكلم IP عام واحد بتاع الـ LB، والسيرفرات نفسها بتتكلم على private IPs مش ظاهرة للإنترنت.
سيرفر وقع؟ الـ LB يحوّل الترافيك على الباقيين وخلاص. الترافيك زاد؟ ضيف سيرفرات للـ pool والـ LB يبتدي يبعتلهم تلقائي.
نسخ الداتابيز
نسخة رئيسية (Primary) بتستقبل الكتابة بس، ونسخ (Replicas) بتاخد نسخة من الداتا وبتخدم القراءة. أغلب التطبيقات القراءة فيها أكتر بكتير من الكتابة، فعدد الـ replicas بيبقى أكبر.
| المكسب | ليه؟ |
|---|---|
| Performance | القراءات بتتوزع على كذا نسخة بالتوازي |
| Reliability | لو سيرفر اتدمر، الداتا موجودة في أماكن تانية |
| Availability | نسخة وقعت؟ الشغل يكمل من نسخة تانية |
الكاش: الدرج اللي جنبك
بدل ما كل مرة تنزل المخزن (الداتابيز) تجيب نفس الحاجة، تحطها في درج جنبك في الميموري. الكاش تخزين مؤقت وسريع للحاجات التقيلة أو اللي بتتطلب كتير.
أدوات شائعة: Memcached و Redis، بـ API بسيط زي set(key, value, ttl) و get(key).
| النقطة | المعنى بالمصري |
|---|---|
| إمتى أستخدمه | الداتا بتتقرى كتير وبتتغير قليل. ومتخزنش فيه حاجة مهمة لوحدها — الميموري بتتمسح لو السيرفر عمل restart |
| Expiration | لازم مدة صلاحية. قصيرة قوي = هترجع للداتابيز كتير. طويلة قوي = داتا بايتة |
| Consistency | الكتابة في الداتابيز والكاش مش في transaction واحدة، فممكن يحصل اختلاف |
| SPOF | كاش سيرفر واحد = نقطة فشل واحدة. خلّي عندك أكتر من سيرفر |
| Eviction | الكاش اتملى؟ ترمي حاجة. الأشهر LRU (الأقدم استخدامًا)، وفيه LFU و FIFO |
الـ CDN: فروع قريبة من اليوزر
شبكة سيرفرات منتشرة في العالم بتشيل المحتوى الثابت: صور، فيديو، CSS، JS. اليوزر اللي في القاهرة ياخد الصورة من أقرب سيرفر ليه بدل ما تيجي من أمريكا.
سيرفر من غير ذاكرة
عشان نكبّر الـ web tier بالعرض بحرية، لازم نشيل الـ state (زي الـ session بتاعة اليوزر) من جوه السيرفر.
بيانات اليوزر A محفوظة في Server 1 بس. يبقى لازم كل ريكوست بتاعه يروح لـ Server 1 (sticky sessions). إضافة أو شيل سيرفر بقت وجع دماغ، والـ failover صعب.
الـ session متخزنة في مكان مشترك (Redis أو NoSQL أو RDBMS). أي سيرفر يقدر يخدم أي ريكوست. تقدر تعمل auto-scaling براحتك.
أكتر من Data Center
لما يبقى عندك يوزرز في كذا قارة، بتوزع السيستم على كذا داتا سنتر. الـ GeoDNS بيوجّه كل يوزر لأقرب داتا سنتر ليه. ولو داتا سنتر وقع كله، الترافيك يروح على اللي شغال.
صندوق البوستة: Message Queue
كومبوننت بيخزن رسايل وبيسمح بشغل asynchronous. الـ Producer بيرمي رسالة في الطابور، والـ Consumer بيسحبها ويشتغل عليها لما يفضى.
المزية الكبيرة decoupling: الـ producer يقدر يبعت حتى لو الـ consumer مش متاح. ولو الطابور كبر، زوّد workers. لو فاضي، قلّلهم.
اللوجز والمقاييس والأوتوميشن
لما السيستم يكبر، لازم تشوف جواه وتشغّله من غير ما تعمل كل حاجة بإيدك.
| الأداة | الفايدة |
|---|---|
| Logging | تتابع الإيرورز. الأحسن تجمعها في مكان مركزي بدل ما تدخل على كل سيرفر |
| Metrics | Host: CPU وميموري و Disk I/O. Aggregated: أداء الداتابيز كطبقة. Business: DAU و retention و revenue |
| Automation | CI بيتأكد إن كل commit سليم، وأوتوميشن للـ build والتيست والـ deploy |
تكبير الداتابيز: Sharding
نفس فكرة الـ web tier. Vertical (ماكينة أقوى) ليه سقف وتكلفته عالية وبيبقى SPOF. Horizontal = sharding: تقسم الداتا على كذا داتابيز.
كل shard ليه نفس الـ schema بس فيه جزء مختلف من الداتا. بتختار sharding key (زي user_id) ودالة زي user_id % 4 تحدد اليوزر ده في أنهي shard. أهم قاعدة: اختار key يوزّع الداتا بالتساوي.
| المشكلة | الشرح والحل |
|---|---|
| Resharding | shard اتملى أو التوزيع مش متساوي، فلازم تغيّر الدالة وتنقل داتا. الحل الشهير: Consistent Hashing (الفصل الجاي) |
| Celebrity / Hotspot | shard عليه يوزرز مشاهير فبيتضرب ضرب. الحل: تدي كل مشهور shard لوحده، أو تقسم أكتر |
| Join | الـ JOIN بين shards صعب. الحل الشائع: de-normalize وتكرر الداتا عشان الكويري يتعمل على جدول واحد |
ممكن كمان تنقل حاجات من الداتابيز لـ NoSQL عشان تخفف الحمل، خصوصًا الداتا اللي مش محتاجة علاقات.
السيستم في شكله الأخير
وبعد الويب: كاش + داتابيز متقسمة ونسخها، وطابور و workers، ولوجز ومقاييس و CI، على أكتر من داتا سنتر.