System Designتصميم e-commerce.
لو اتسألت "صمّم نظام e-commerce من الصفر" — ده الـ artifact بتاعك. المنهجية الكاملة: إزاي تبدأ، المكوّنات المعمارية، المقايضات، وإزاي توسّع لملايين المستخدمين. مع ربط بـ Magento حيث يفيد.
عشان تصمّم نظام e-commerce في الإنترفيو، ابدأ بتوضيح المتطلبات وتقدير الحجم، وبعدين ارسم المعمارية: load balancer، و application servers، و database بنسخ للقراءة، و cache، و queue للشغل غير المتزامن، و search engine. بعدها ناقش التوسّع ومشاكل التجارة الإلكترونية زي تضارب المخزون والدفع المكرّر والمقايضات بين الحلول.
المنهجية — إزاي تبدأ
الإطار اللي بتمشي عليه في أي سؤال system design. احفظ الترتيب ده.
أي سؤال system design بيتحل بنفس الإطار. لو مشيت عليه بترتيب، بتبان منظّم ومحترف.
- وضّح المتطلبات — اسأل أسئلة. مين المستخدمين؟ إيه الـ features الأساسية؟ الحجم؟
- قدّر الحجم — عدد المستخدمين، الطلبات في الثانية، حجم البيانات.
- ارسم المعمارية العامة — المكوّنات الرئيسية وإزاي بتتكلم.
- غُص في التفاصيل — الـ DB schema، الـ APIs، المكوّن الأصعب.
- ناقش المقايضات والتوسّع — bottlenecks، caching، scaling، failure.
توضيح المتطلبات
أهم خطوة. تفصل المتطلبات لنوعين: وظيفية وغير وظيفية.
FUNCTIONALوظيفية
- تصفّح المنتجات
- بحث وفلترة
- سلة وطلبات
- دفع (payment)
- حسابات المستخدمين
- إدارة المخزون
NON-FUNCغير وظيفية
- توفّر عالي (availability)
- سرعة (latency)
- قابلية التوسّع
- اتساق البيانات
- أمان (المدفوعات)
- تحمّل الضغط
الـ وظيفية بتحدد "النظام بيعمل إيه". الـ غير وظيفية بتحدد "بيعمله كويس إزاي" — وهي اللي بتشكّل المعمارية فعليًا. مثلًا "توفّر عالي" بيفرض redundancy، و"سرعة" بتفرض caching.
التقديرات (Scale)
تقدير الأرقام بيوجّه قراراتك المعمارية. مش لازم دقيق، بس منطقي.
افترض 10 مليون مستخدم، 1 مليون نشط يوميًا. لو كل واحد بيتصفّح 20 صفحة، ده ~20 مليون طلب يوميًا. اقسم على 86400 ثانية = ~230 طلب/ثانية متوسط، والذروة ممكن 5x = ~1000+ طلب/ثانية.
- Read vs Write ratio: في e-commerce، القراءة أكتر بكتير (تصفّح) من الكتابة (شراء). نسبة زي 100:1 شائعة.
- الخلاصة المعمارية: النظام read-heavy — يعني الـ caching والـ read replicas هيكونوا محوريين.
- حجم البيانات: ملايين المنتجات × بياناتها + الطلبات + المستخدمين = تقدير للـ storage.
المعمارية عالية المستوى
الرسمة اللي بترسمها للمُقابِل. المكوّنات الرئيسية وتدفّق الطلب.
الطلب بيجي من الـ client، يعدّي على الـ CDN (للمحتوى الثابت) والـ load balancer، يتوزّع على الـ services، اللي بتقرا من الـ cache الأول وبعدين الـ DB، والعمليات التقيلة بتتحوّل للـ queue.
المكوّنات الأساسية
دور كل مكوّن، وليه محتاجينه.
بيوزّع الطلبات على عدة سيرفرات عشان محدش يقع تحت الضغط. بيوفّر توسّع أفقي وتحمّل الأعطال (لو سيرفر وقع، الباقي بيشيلوا).
بيخزّن المحتوى الثابت (صور، CSS، JS) في سيرفرات قريبة جغرافيًا من المستخدم. بيقلّل الـ latency وبيخفّف الحمل على السيرفر الأساسي.
لأن النظام read-heavy. الـ cache بيخزّن النتايج المتكررة في الذاكرة (سريعة جدًا) بدل ما يحسبها أو يجيبها من الـ DB كل مرة.
- Full-page cache: صفحات كاملة (منتج، category) — الأثقل تأثيرًا.
- Object cache: نتايج queries أو حسابات (Redis/Memcached).
- CDN cache: المحتوى الثابت على الحافة.
عشان تفصل العمليات البطيئة عن مسار الطلب الأساسي. المستخدم مش لازم يستنى إرسال إيميل تأكيد أو تحديث نظام خارجي — دي بتروح للـ queue وتتنفّذ في الخلفية.
- إرسال إيميلات / إشعارات
- تحديث أنظمة خارجية (ERP)
- معالجة تقارير تقيلة
- تحديثات المخزون المؤجّلة
البحث النصّي والفلترة المعقّدة (facets) بطيئة جدًا على DB عادية مع ملايين المنتجات. محرك بحث مخصّص زي Elasticsearch مبني للغرض ده — بحث سريع، فلترة، وترتيب بالصلة.
قاعدة البيانات
اختيار وتصميم الـ DB، وأهم المقايضات.
مش لازم تختار واحد. Polyglot persistence — كل نوع بيانات في الـ DB المناسبة ليه:
- SQL (MySQL/Postgres) — للطلبات والمدفوعات والمخزون. محتاجة ACID transactions (اتساق قوي).
- NoSQL — للـ sessions، الـ carts المؤقتة، أو الـ catalog اللي محتاج قراءة سريعة ومرونة.
- Search index — Elasticsearch للبحث.
- Cache — Redis للبيانات السريعة المؤقتة.
- Read Replicas: نسخ للقراءة بس. مثالية للنظام read-heavy — القراءة تتوزّع، الكتابة تروح للـ master.
- Sharding: تقسيم البيانات على عدة DBs (مثلًا حسب الـ region أو الـ user id) لما البيانات تكبر جدًا.
- Indexing: فهارس على الأعمدة المستخدمة في البحث والفلترة.
- Denormalization: تكرار بعض البيانات لتسريع القراءة (زي فكرة الـ index tables).
التوسّع (Scaling)
إزاي تتعامل مع نمو المستخدمين. المبادئ العامة.
- Vertical (سيرفر أقوى): أسهل بس ليه سقف، ونقطة فشل واحدة.
- Horizontal (سيرفرات أكتر): الأفضل للتوسّع الكبير — بتضيف أجهزة بدل ما تكبّر واحد.
الـ services لازم تكون stateless — متخزّنش حالة المستخدم محليًا. الحالة (زي الـ session) بتروح لـ store مشترك (Redis) عشان أي سيرفر يقدر يخدم أي مستخدم.
مش دايمًا microservices أحسن. الـ monolith (زي Magento) أبسط في البداية وأسرع تطوير. الـ microservices بتفيد لما الفريق يكبر والأجزاء تحتاج توسّع مستقل — بس بتضيف تعقيد شبكي كبير.
تحديات e-commerce الخاصة
المشاكل اللي بتميّز الـ e-commerce عن أي نظام تاني — دي اللي بتفرّقك.
لو آخر قطعة في المخزون، ومستخدمين اتنين طلبوها في نفس اللحظة — مين ياخدها؟ ده race condition كلاسيكي في e-commerce (oversell problem).
1) Database locking (pessimistic/optimistic) عند خصم المخزون. 2) Reserve on add-to-cart — تحجز الكمية مؤقتًا. 3) Atomic operations في الـ DB تضمن إن الخصم يحصل مرة واحدة.
الدفع لازم يكون موثوق ومتّسق تمامًا. مينفعش يتخصم من العميل والطلب ميتعملش، أو العكس. وكمان لازم آمن (PCI compliance).
- Idempotency: لو الطلب اتبعت مرتين (بسبب retry)، ميتخصمش مرتين. مفتاح فريد لكل عملية.
- Payment gateway خارجي: متخزّنش بيانات الكروت بنفسك — استخدم Stripe/PayPal.
- Saga pattern: للعمليات الموزّعة، لو خطوة فشلت، الباقي بيترجع (compensating transactions).
في عروض زي Black Friday، الضغط بيقفز عشرات الأضعاف فجأة. النظام لازم يستحمّل أو "يتعطّل بلطف" (graceful degradation).
- Auto-scaling: إضافة سيرفرات أوتوماتيك مع الضغط.
- Queue-based load leveling: استقبال الطلبات في queue ومعالجتها بمعدّل ثابت.
- Rate limiting: حماية النظام من الانهيار.
- Aggressive caching: تخفيف الحمل عن الـ DB قدر الإمكان.
سيناريو كامل — مثال
إزاي تجمّع كل ده في إجابة واحدة متماسكة.
- أسأل: كام مستخدم؟ B2C ولا B2B؟ عالمي ولا محلي؟ الـ features الأساسية؟
- أقدّر: read-heavy، ~1000 طلب/ثانية ذروة، ملايين المنتجات.
- أرسم: Client → CDN → LB → Services (Catalog/Cart/Order/Payment) → Cache + DB + Queue + Search.
- أفصّل المخزون: مشكلة الـ race condition وحلها بالـ reservations.
- أفصّل الدفع: gateway خارجي + idempotency + اتساق قوي.
- أوسّع: read replicas للقراءة، caching للصفحات، queue للعمليات البطيئة.
- أناقش المقايضات: اتساق المخزون vs سرعة العرض، monolith vs services.
System Design ✓
دلوقتي عندك المنهجية الكاملة لأي سؤال system design في e-commerce: من توضيح المتطلبات، للمعمارية، للتوسّع، وتحديات المجال الخاصة. والأهم — طريقة التفكير المنظّمة.
افتكر: المُقابِل بيقيّم منهجيتك ومقايضاتك، مش إجابة واحدة صح. فكّر بصوت عالي، اسأل الأول، واشرح "ليه" مع كل قرار. ده اللي بيميّز الـ senior.
خلّصت الدرس؟علّمه عشان تتابع تقدّمك في الكورس.
أسئلة شائعة
إزاي أبدأ أجاوب على سؤال System Design في الإنترفيو؟
امشي على خمس خطوات بالترتيب: وضّح المتطلبات، قدّر الحجم، ارسم المعمارية العامة، غُص في التفاصيل، وبعدين ناقش المقايضات والتوسّع. اقضِ أول 5 دقايق في الأسئلة مش الرسم، لأن المُقابِل بيقيّم منهجيتك ومقايضاتك مش حفظك.
ما الفرق بين المتطلبات الوظيفية وغير الوظيفية في System Design؟
الوظيفية بتحدد النظام بيعمل إيه، زي تصفّح المنتجات والبحث والسلة والدفع. غير الوظيفية بتحدد بيعمله كويس إزاي، زي الـ availability والـ latency والـ scalability والأمان، وهي اللي بتشكّل المعمارية فعليًا: التوفّر العالي بيفرض redundancy والسرعة بتفرض caching.
ليه نظام الـ e-commerce بيتقال عليه read-heavy وده بيأثر على التصميم إزاي؟
في الـ e-commerce القراءة (التصفّح) أكتر بكتير من الكتابة (الشراء)، ونسبة زي 100:1 شائعة. عشان كده الـ caching بأنواعه (full-page وobject وCDN) والـ read replicas بيبقوا محوريين في التصميم، وأصعب جزء في الـ caching هو الـ invalidation.
SQL ولا NoSQL لمتجر إلكتروني؟
مش لازم تختار واحد، الإجابة المتوازنة هي polyglot persistence. الطلبات والمدفوعات والمخزون في SQL عشان محتاجة ACID transactions واتساق قوي، والـ sessions والـ carts المؤقتة ممكن تبقى NoSQL، والبحث في Elasticsearch، والبيانات السريعة المؤقتة في Redis.
ما الفرق بين Horizontal و Vertical scaling؟
الـ Vertical معناه تكبّر سيرفر واحد، وده أسهل بس ليه سقف ونقطة فشل واحدة. الـ Horizontal معناه تضيف سيرفرات أكتر، وده الأفضل للتوسّع الكبير، بشرط إن الـ services تكون stateless والـ session تتخزّن في store مشترك زي Redis.
إزاي أمنع بيع آخر قطعة في المخزون لعميلين في نفس اللحظة؟
دي race condition كلاسيكية اسمها oversell problem. حلولها: database locking (pessimistic أو optimistic) عند خصم المخزون، أو حجز الكمية مؤقتًا عند الإضافة للسلة، أو atomic operations في الـ DB تضمن إن الخصم يحصل مرة واحدة.
إزاي أمنع الدفع المزدوج في نظام e-commerce؟
الحل هو idempotency key: مفتاح فريد لكل عملية دفع، فلو الطلب اتبعت مرتين بسبب retry ميتخصمش مرتين. ومعاه استخدم payment gateway خارجي زي Stripe أو PayPal بدل ما تخزّن بيانات الكروت بنفسك، والـ Saga pattern للعمليات الموزّعة.