MongoDB: التجزئة: التوسع الأفقي

آخر تحديث: 2026-08-26

تُعد المجموعات المقسمة (Sharded clusters) الحل الأمثل للتوسع الأفقي في MongoDB — حيث يتيح لك إتقان استخدامها دعم البيانات التي تصل إلى حجم البيتابايت.

1. ما ستتعلمه



2. البنية المقسمة

شرح المفهوم: التجزئة (Sharding) هي حل التوسع الأفقي في MongoDB — حيث تعمل على توزيع البيانات عبر عدة شاردات، كل منها عبارة عن مجموعة نسخ متماثلة مستقلة. وتقوم التطبيقات بالوصول إلى البيانات بشكل شفاف من خلال توجيه Mongos، دون الحاجة إلى معرفة كيفية توزيع البيانات. وعندما يصل خادم واحد إلى سعته القصوى أو إلى الحد الأقصى لمعدل نقل البيانات للكتابة، فإن التجزئة هي الطريقة الوحيدة للتوسع.

كيفية العمل: يعمل Mongos كموجه للاستعلامات. بعد تلقي طلب من التطبيق، يسترد بيانات تعريف الشرائح (أي الأجزاء الموجودة على أي شرائح) من خادم التكوين (Config Server)، ثم يوجه الطلب إلى الشريحة المستهدفة لتنفيذه، ويقوم بدمج النتائج قبل إرجاعها. ويكون كود التطبيق مطابقًا لكود MongoDB ذي العقدة الواحدة — حيث تكون عملية تقسيم البيانات إلى شرائح شفافة بالنسبة للتطبيق.

ثلاثة مكونات رئيسية:

100%
graph TB
    App[Applications] --> M[Mongos<br/>Query Route<br/>Stateless]
    M --> CS[Config Server<br/>Configuration Information<br/>3Node Replica Set]
    M --> S1[Shard 1<br/>Shard Node 1<br/>Dungeon Collection]
    M --> S2[Shard 2<br/>Shard Node 2<br/>Dungeon Collection]
    M --> S3[Shard 3<br/>Shard Node 3<br/>Dungeon Collection]

    subgraph "Data Flow"
        Q[Query Request] --> M
        M -->|Metadata Query| CS
        M -->|Data Query| S1
        M -->|Data Query| S2
        M -->|Data Query| S3
    end

    style M fill:#cce5ff
    style CS fill:#fff3cd
    style S1 fill:#d4edda
    style S2 fill:#d4edda
    style S3 fill:#d4edda
المكون المسؤوليات متطلبات النشر
Mongos توجيه الاستعلامات، شفافية التطبيق لا يعتمد على الحالة، يدعم مثيلات متعددة
خادم التكوين يخزن البيانات الوصفية للشارد (تكوين المجموعة) يجب أن يكون مجموعة نسخ متماثلة (3 عقد)
الشارد يخزن البيانات الفعلية (كل شارد عبارة عن مجموعة نسخ متماثلة) مجموعة نسخ متماثلة تضم 3 عقد على الأقل

الشظايا مقابل مجموعات النسخ المتماثلة:

البعد مجموعة النسخ المتماثلة مجموعة الشاردات
الهدف التوافر العالي (HA) التوسع الأفقي + التوافر العالي (HA)
البيانات تخزن كل عقدة مجموعة البيانات بالكامل يتم توزيع البيانات عبر شظايا متعددة
توسيع نطاق الكتابة لا شيء (تُوجه جميع عمليات الكتابة إلى الخادم الأساسي) ✅ توزيع عمليات الكتابة على شظايا متعددة
قابلية التوسع في القراءة موازنة الحمل الثانوية للقراءة ✅ الاستعلامات المتوازية متعددة الأجزاء
تعقيد العمليات متوسط مرتفع
النطاق المناسب < 1 تيرابايت > 1 تيرابايت / > 10 آلاف عملية في الثانية


3. استراتيجيات اختيار مفتاح التجزئة

شرح المفهوم: مفتاح التجزئة هو الحقل الذي يحدد كيفية توزيع البيانات عبر الشرائح — وهو يؤثر بشكل مباشر على أداء الاستعلامات، وتوازن البيانات، وقابلية التوسع. وبمجرد تعيين مفتاح التجزئة، لا يمكن تعديله؛ ويُعد اختيار مفتاح تجزئة خاطئ أحد أخطر الأخطاء في التصميم المعماري.

كيفية العمل: يقسم MongoDB البيانات إلى أجزاء (64 ميغابايت افتراضيًا) بناءً على مفتاح التجزئة، حيث يتم تخصيص كل جزء لشظية معينة. تعمل التجزئة النطاقية على تقسيم البيانات بناءً على نطاقات قيم مفتاح التجزئة، بينما تعمل التجزئة التجزئية على تقسيم البيانات بناءً على قيم التجزئة لمفتاح التجزئة. أثناء إجراء استعلام، يستخدم Mongos مفتاح التجزئة لتحديد موقع الجزء الذي يحتوي على القطعة المستهدفة، وبذلك يتجنب استعلامات البث.

قواعد ESRT لاختيار مفتاح التجزئة:

الترتيب النوع الوصف مثال
المساواة التصفية على أساس القيمة المتساوية تفضيل userId، _id find({userId: 'u001'})
الفرز حقل الفرز createdAt، إلخ. sort({createdAt: -1})
النطاق استعلام النطاق تحديد النطاقات المتكررة {price: {$gte: 100}}
الزمن الاتجاه الزمني بيانات السلسلة الزمنية {createdAt: 1}

أربع خصائص لمفتاح التقسيم الجيد:

الميزة الوصف السبب
خط أساس مرتفع عدد كبير من القيم الفريدة يمكن تقسيم البيانات إلى أجزاء أكثر تفصيلًا
تحديثات نادرة القيم نادرًا ما تتغير يتطلب تغيير مفتاح الشارد ترحيل القطع، وهو ما يستهلك موارد كثيرة
مطابقة الاستعلام تشمل شروط الاستعلام مفتاح الشارد يدعم Mongos التوجيه الموجه لتجنب البث
التوزيع المتساوي القيم موزعة بشكل متساوٍ تجنب شظايا النقاط الساخنة

(1) تجزئة النطاقات (تقسيم النطاقات)

شرح المفهوم: تقسم تقنية تجزئة النطاق (Range sharding) المجموعات بناءً على الترتيب الطبيعي لقيم مفتاح التجزئة — حيث تُوضع نطاقات القيم المتتالية في نفس المجموعة. وتُعد هذه التقنية مناسبة لاستعلامات النطاق والفرز، لكنها قد تؤدي بسهولة إلى انحراف البيانات (النقاط الساخنة).

المبدأ: تقسم تقنية تجزئة النطاق (Range sharding) نطاق قيم مفتاح التجزئة إلى فترات متجاورة [min, splitPoint1), [splitPoint1, splitPoint2), ...، حيث تتوافق كل فترة مع «كتلة» (chunk). وتُوضع المستندات ذات القيم المتجاورة في نفس «الكتلة» → نفس «الشارد».

JAVASCRIPT
// === Enable Sharding ===
sh.enableSharding('shopdb');

// === Selecting a Sharding Key:User ID Scope ===
sh.shardCollection('shopdb.orders', { userId: 1 });
// userId 1-1000 → Shard 1
// userId 1001-2000 → Shard 2
البعد شظايا النطاق الوصف
استعلام النطاق ✅ فعال بيانات متتالية في نفس الشارد
الفرز ✅ فعال الفهارس مرتبة ترتيبًا طبيعيًّا
توزيع البيانات ⚠️ احتمال حدوث انحراف تركز مفاتيح الاختصار في شارد واحد
السيناريوهات المناسبة السلاسل الزمنية، نطاق المعرفات createdAt، userId

(2) الشظايا المُجزأة

شرح المفهوم: تعمل تقنية «التجزئة التجزئية المُجزأة» (Hashed sharding) على حساب قيمة التجزئة لمفتاح الشارد وتقسيم المجموعات بناءً على نطاقات قيم التجزئة. يتم توزيع البيانات بالتساوي دون وجود نقاط ازدحام، لكن استعلامات النطاق تتطلب إرسال بث إلى جميع الشاردات.

JAVASCRIPT
// === Hash Sharding ===
sh.shardCollection('shopdb.products', { sku: 'hashed' });
// sku Hash values are evenly distributed across the shards
البعد الشظية المُجزَّأة الوصف
توزيع البيانات ✅ متجانس موزعة بشكل طبيعي بواسطة دالة التجزئة
توزيع الكتابة ✅ متجانس لا توجد نقاط ساخنة
استعلام النطاق ❌ يتطلب البث القيم المتجاورة موجودة في شاردات مختلفة
السيناريوهات المناسبة استعلامات المساواة بشكل أساسي SKU، البريد الإلكتروني، معرّف المستخدم

(3) المقارنة بين نطاق البحث والمقارنة التجزئية

البعد النطاق التجزئة
توزيع البيانات الانحراف المحتمل التوزيع المنتظم
استعلام النطاق ✅ المسار المستهدف ❌ البث إلى جميع الشاردات
استعلام التكافؤ
الفرز ✅ مُرتبة حسب الفهرس
نقاط التلامس ⚠️ نقاط التلامس أحادية النقطة ✅ موحدة
المفاتيح المركبة المقسمة ✅ مدعومة ❌ حقل واحد فقط

(4) اختيار أفضل مفتاح تقسيم

JAVASCRIPT
// ✅ Good Sharding Key:High base figure、Infrequent Updates、Query hits
sh.shardCollection('shopdb.orders', { userId: 1, createdAt: -1 });
// Composite Segmented Key,userId Scope + Sort by Time

// ❌ Invalid Shard Key:Low base
sh.shardCollection('shopdb.products', { category: 1 });
// category Only 5 a value,It will tilt severely

النمط الخاطئ لمفتاح التقسيم:

النمط الخاطئ العواقب أفضل الممارسات
حقل ذو قيمة منخفضة (مثل: الفئة) انحراف شديد في البيانات اختيار حقل ذو قيمة عالية (userId)
حقل يتزايد بشكل أحادي (مثل ObjectId) تُكتب جميع البيانات الجديدة في نفس الشارد استخدم مفتاح تجزئة مجزأ أو مركب
الحقول التي يتم تحديثها بشكل متكرر الترحيل المتكرر للكتل تحديد الحقول التي يتم تحديثها بشكل غير متكرر
غير موجود في معايير الاستعلام جميع عمليات بث الاستعلامات تحديد حقول الاستعلام عالية التكرار


4. تقسيم المجموعات وترحيلها

شرح المفهوم: «الشانك» (Chunk) هو أصغر وحدة في إدارة البيانات المقسمة إلى شاردات — 64 ميغابايت بشكل افتراضي — ويحتوي على جميع المستندات التي تقع مفاتيح شارداتها ضمن نطاق معين. يتم تقسيم الشانكات تلقائيًا عندما تتجاوز حدًا معينًا، كما يتم ترحيلها تلقائيًا عندما يكون عدد الشانكات غير متساوٍ عبر الشاردات. وهذه هي الآلية الأساسية الكامنة وراء ميزانية التحميل التلقائية في MongoDB.

كيف يعمل:

كيف يعمل المعادل الصوتي:

100%
graph TB
    subgraph "Equalizer Workflow"
        A[Check eachShard<br/>ChunkQuantity] --> B{Gap>8?}
        B -->|Yes| C[Select Migration Source Shard<br/>(Chunk with the most)]
        C --> D[Select a Migration DestinationShard<br/>(ChunkThe fewest)]
        D --> E[MigrationChunk]
        E --> F[UpdateConfig Server<br/>Metadata]
        F --> A
        B -->|No| G[Wait for the next check<br/>Default 10 seconds]
    end

    style E fill:#cce5ff
    style F fill:#d4edda
100%
graph LR
    A[Chunk 1<br/>1-1000] -->|Split| B[Chunk 1a<br/>1-500]
    A -->|Split| C[Chunk 1b<br/>501-1000]
    C -->|Migration| D[Shard 2]

    style B fill:#d4edda
    style D fill:#fff3cd

أوامر القطع:

العملية الأمر الوصف
التقسيم يدويًّا sh.splitAt(ns, key) التقسيم عند زوج القيمة والمفتاح المحدد
عرض التوزيع db.col.getShardDistribution() حجم البيانات حسب الشارد
حالة المجموعة sh.status() تفاصيل توزيع الأجزاء
حالة المعادل sh.isBalancerRunning() هل عملية المعادلة جارية؟
معادل التشغيل والإيقاف sh.startBalancer() / sh.stopBalancer() يمكن إيقافه مؤقتًا خلال فترات الصيانة
تغيير حجم المقطع db.settings.save({_id:'chunksize', value: 128}) الوحدة: ميغابايت
JAVASCRIPT
// === Manual Split Chunk ===
sh.splitAt('shopdb.orders', { userId: 5000 });

// === View Chunk Distribution ===
db.orders.getShardDistribution();

// === Balancer Status ===
sh.status();
sh.isBalancerRunning();

تحليل النقاط الرئيسية:

  1. تقسيم المجموعات هو عملية منطقية (فهي لا تؤدي إلا إلى تعديل البيانات الوصفية) ولا تنقل البيانات؛ أما ترحيل المجموعات فهو عملية مادية (فهي تنسخ البيانات فعليًّا).
  2. يعمل المُعادِل في الخلفية ولا يؤثر على عمليات القراءة/الكتابة أثناء عملية الترحيل (باستخدام الكتابة المزدوجة لضمان الاتساق).
  3. خلال فترات الصيانة (مثل عمليات الاستيراد المجمعة)، يُوصى بإيقاف تشغيل المعادل مؤقتًا لمنع أن تؤثر عملية الترحيل على أداء الاستيراد.

▶ المثال 1: إدارة المعادل وتقسيم المقاطع يدويًّا

JAVASCRIPT
// ShopHub:Pause the equalizer before importing a large batch,Restore After Import
// 1. Pause Equalizer
sh.stopBalancer();

// 2. Bulk Import Data
for (let i = 0; i < 1000000; i++) {
  db.orders.insertOne({ userId: 'user_' + (i % 500), total: Math.random() * 1000, createdAt: new Date() });
}

// 3. Manually Split Hotspots Chunk
sh.splitAt('shopdb.orders', { userId: 'user_100' });
sh.splitAt('shopdb.orders', { userId: 'user_200' });
sh.splitAt('shopdb.orders', { userId: 'user_300' });

// 4. Restore the Equalizer
sh.startBalancer();

// 5. Verification Distribution
db.orders.getShardDistribution();

الإخراج:

TEXT 📖 للعرض فقط
Shard shard1 at shard1/host1:27018
  data: 500MB docs: 500000 chunks: 50
Shard shard2 at shard2/host2:27018
  data: 500MB docs: 500000 chunks: 50


5. إعداد مجموعة Docker المقسمة

نظرة عامة على المفهوم: يعد نشر مجموعة مقسمة (sharded cluster) أكثر تعقيدًا من نشر مجموعة النسخ المتماثلة (replica set) — فهو يتطلب مجموعة نسخ متماثلة لخادم التكوين (Config Server)، ومجموعات نسخ متماثلة متعددة للشرائح (shards)، وتوجيه Mongos. ويمكن لـ Docker Compose تنسيق جميع هذه المكونات بأمر واحد، مما يجعله خيارًا مثاليًّا لبيئات التطوير والاختبار.

بنية النشر:

100%
graph TB
    subgraph "Config Server Dungeon Collection"
        CS1[config1:27019]
    end

    subgraph "Shard 1 Dungeon Collection"
        S1A[shard1a:27018]
    end

    subgraph "Shard 2 Dungeon Collection"
        S2A[shard2a:27020]
    end

    subgraph "Mongos Routing"
        MS[mongos:27017]
    end

    App[Applications] --> MS
    MS --> CS1
    MS --> S1A
    MS --> S2A

    style MS fill:#cce5ff
    style CS1 fill:#fff3cd
    style S1A fill:#d4edda
    style S2A fill:#d4edda

مقارنة بين تكوينات الإنتاج وتكوينات التطوير:

المكون بيئة الإنتاج بيئة التطوير
خادم التهيئة مجموعة نسخ متماثلة مكونة من 3 عقد عقدة واحدة (لأغراض الاختبار فقط)
لكل شارد مجموعة نسخ متماثلة مكونة من 3 عقد عقدة واحدة
Mongos مثيلات متعددة (توزيع الحمل) مثيل واحد
العدد الإجمالي لـ mongods 3 + 3 × 3 = 12+ 1 + 2 + 1 = 4
YAML
# docker-compose-sharding.yml
version: '3.8'
services:
  # Config Server(Dungeon Collection)
  config1:
    image: mongo:7.0
    command: mongod --configsvr --replSet configReplSet --port 27019

  # Shard 1(Dungeon Collection)
  shard1a:
    image: mongo:7.0
    command: mongod --shardsvr --replSet shard1ReplSet --port 27018

  # Mongos Routing
  mongos:
    image: mongo:7.0
    command: mongos --configdb configReplSet/config1:27019 --port 27017
    ports:
      - "27017:27017"

خطوات التهيئة:

الخطوة الأمر الوصف
1 rs.initiate() على config1 تهيئة مجموعة النسخ المتماثلة لخادم التكوين
2 rs.initiate() على shard1a تجري عملية تهيئة مجموعة النسخ المتماثلة للشارد 1
3 sh.addShard() على mongos إضافة شارد إلى المجموعة
4 sh.enableSharding() تمكين تجزئة قاعدة البيانات
5 sh.shardCollection() حدد مفتاح الشارد
BASH
# === Initialize a sharded cluster ===
# 1. Initialization Config Server Dungeon Collection
mongosh --port 27019 --eval 'rs.initiate({_id: "configReplSet", members: [{_id: 0, host: "config1:27019"}]})'

# 2. Initialization Shard 1 Dungeon Collection
mongosh --port 27018 --eval 'rs.initiate({_id: "shard1ReplSet", members: [{_id: 0, host: "shard1a:27018"}]})'

# 3. Through Mongos Add a shard
mongosh --port 27017 --eval '
  sh.addShard("shard1ReplSet/shard1a:27018");
  sh.enableSharding("shopdb");
  sh.shardCollection("shopdb.orders", { userId: 1 });
'


6. مراقبة المجموعات المقسمة

شرح المفهوم: تعد مراقبة الكتلة المقسمة (sharded cluster) أكثر تعقيدًا من مراقبة عقدة فردية أو مجموعة النسخ المتماثلة — فهي تتطلب مراقبة حالة كل مكون، وتوازن توزيع البيانات، وحالة ترحيل الأجزاء (chunk)، وغير ذلك. ويمكن أن تساعد المراقبة السليمة في الكشف عن انحراف البيانات، والشظايا المثقلة (hot shards)، ومشكلات التكوين في الوقت المناسب.

أبعاد الرصد:

البعد الأمر المؤشرات الرئيسية
نظرة عامة على المجموعة sh.status() عدد الشاردات، توزيع القطع، حالة أداة موازنة الحمل
توزيع البيانات db.col.getShardDistribution() هل حجم البيانات موزع بشكل متوازن بين الشاردات؟
معادل الصوت sh.isBalancerRunning() حالة الترحيل، تقدم عملية الترحيل
معلومات التكوين db.settings.find() حجم المقطع، تكوين المعادل
صحة الشارد sh.status().shards إمكانية الوصول إلى الشارد
JAVASCRIPT
// === View Shard Status ===
sh.status();

// === Data Distribution ===
db.orders.getShardDistribution();

// === Balancer Management ===
sh.startBalancer();
sh.stopBalancer();
sh.setBalancerState(true);

// === Layout ===
db.settings.find();

حل المشكلات الشائعة:

المشكلة الأعراض التشخيص الحل
انحراف البيانات حجم البيانات في شارد معين أكبر بكثير من حجمها في الشاردات الأخرى getShardDistribution() تقسيم القطع الأكثر استخدامًا يدويًّا
جزء ضخم لا يمكن تقسيم الأجزاء التي يزيد حجمها عن 64 ميغابايت sh.status() إظهار الأجزاء الضخمة قم بزيادة حجم الجزء أو قسّم المفتاح
تعطل المعادل الترحيل لا يتقدم sh.isBalancerRunning() التحقق من حالة خادم التكوين
بث الاستعلام تم الاستعلام عن جميع الشاردات explain() يُظهر SHARD_MERGE تشمل شروط الاستعلام مفتاح الشاردة

▶ المثال 2: مراقبة الشاردات واستكشاف الأعطال وإصلاحها

JAVASCRIPT
// Bob's DataFlow system has detected that queries are running slowly, diagnosing sharding issues
// 1. View Cluster Status
sh.status();
// Discovery Shard1: 8000 chunks, Shard2: 2000 chunks → Severe tilt

// 2. View Data Distribution
db.orders.getShardDistribution();
// Shard 1: 80GB (80%), Shard 2: 20GB (20%)

// 3. Check to see if there is Jumbo Chunk
db.config.chunks.find({ jumbo: true }).count();
// 3 Jumbo Chunks

// 4. Manually Split Hotspots Chunk
sh.splitAt('shopdb.orders', { userId: 'user_100' });
sh.splitAt('shopdb.orders', { userId: 'user_200' });

// 5. Verify that the equalizer is running
sh.startBalancer();
sh.isBalancerRunning(); // true

// 6. Waiting for the balancing process to complete,Check again
db.orders.getShardDistribution();
// Shard 1: 50GB (50%), Shard 2: 50GB (50%) → Balance

الإخراج:

TEXT 📖 للعرض فقط
Shard 1: 50GB (50%), Shard 2: 50GB (50%) → Balance


7. متى ينبغي استخدام تقنية التقسيم (Sharding)؟

شرح المفهوم: لا يُعد تنفيذ تقسيم البيانات (الشاردينغ) في أقرب وقت ممكن هو الخيار الأمثل دائمًا — ففي حين أنه يوفر قابلية التوسع، إلا أنه يزيد أيضًا من تعقيد العمليات التشغيلية. فقد يؤدي تنفيذ تقسيم البيانات في وقت مبكر جدًّا إلى تكاليف تشغيلية غير ضرورية؛ في حين أن تأخير تنفيذه قد يؤدي إلى اختناقات في الخادم الفردي وصعوبات في ترحيل البيانات. وينبغي أن يستند القرار إلى تقييم شامل لحجم البيانات، ومعدل إنتاجية الكتابة، واتجاهات النمو.

إطار اتخاذ القرار:

100%
graph TB
    A{Data volume?} -->|< 100GB| B[❌ Single-player + Dungeon Collection]
    A -->|100GB-1TB| C{WriteQPS?}
    A -->|> 1TB| D[✅ Sharding]
    C -->|< 10K ops/s| E[⚠️ Dungeon Collection<br/>Monitor Growth Trends]
    C -->|> 10K ops/s| D

    B --> F[Optimize Indexes + Search]
    E --> G[Pre-planned Sharding Keys]
    D --> H[Select a partition key + Deploy a Sharded Cluster]

    style B fill:#d4edda
    style D fill:#cce5ff
    style E fill:#fff3cd
السيناريو تقسيم البيانات السبب
حجم البيانات < 100 جيجابايت ❌ يكفي استخدام خادم واحد يؤدي تقسيم البيانات إلى زيادة التعقيد دون تقديم أي فوائد
حجم البيانات: 100 جيجابايت – 1 تيرابايت ⚠️ يعتمد على الحالة تقييم معدل عمليات الكتابة في الثانية (QPS) ومعدل النمو
حجم البيانات > 1 تيرابايت ✅ موصى به سعة الخادم الواحد واختناقات الإدخال/الإخراج
الكتابة > 10 آلاف عملية في الثانية ✅ موصى به عنق زجاجة وحيد في الكتابة الأساسية
حجم البيانات في تزايد مستمر ✅ موصى به التخطيط المسبق لتجنب التقسيم القسري

قائمة التحقق قبل تقسيم الشبكة:

بند التحضير الوصف
تأكد من أن تحسين الفهرس غير ممكن استخدم أولاً explain() لاستبعاد مشاكل الاستعلامات
تأكد من أن التوسع الرأسي غير ممكن هل ستكون ترقية وحدة المعالجة المركزية والذاكرة ومحرك الأقراص SSD كافية؟
اختيار مفتاح التقسيم المناسب عدد السجلات الكبير، وتكرار التحديث المنخفض، ونتائج الاستعلام
نشر مجموعة النسخ المتماثلة أساس تقسيم البيانات إلى شرائح؛ كل شريحة هي مجموعة نسخ متماثلة
السعة المخطط لها تقدير معدل نمو البيانات وتحديد عدد الشاردات
اختبار توافق التطبيقات تأكد من أن الاستعلامات تتضمن مفتاح التجزئة وأن الفهارس الفريدة تتضمن مفتاح التجزئة

▶ مثال: دليل عملي لنشر مجموعة مقسمة باستخدام Docker + تقسيم البيانات

BASH
# === 1. Start the sharded cluster(docker-compose-sharding.yml)===
# services:
#   config1:
#     image: mongo:7.0
#     command: mongod --configsvr --replSet configReplSet --bind_ip_all --port 27019
#     ports: ["27019:27019"]
#
#   shard1a:
#     image: mongo:7.0
#     command: mongod --shardsvr --replSet shard1ReplSet --bind_ip_all --port 27018
#     ports: ["27018:27018"]
#
#   shard2a:
#     image: mongo:7.0
#     command: mongod --shardsvr --replSet shard2ReplSet --bind_ip_all --port 27020
#     ports: ["27020:27020"]
#
#   mongos:
#     image: mongo:7.0
#     command: mongos --configdb configReplSet/config1:27019 --bind_ip_all --port 27017
#     ports: ["27017:27017"]
#     depends_on: [config1, shard1a, shard2a]

docker-compose -f docker-compose-sharding.yml up -d

# === 2. Initialization Config Server Dungeon Collection ===
mongosh --port 27019 --eval '
  rs.initiate({
    _id: "configReplSet",
    members: [{ _id: 0, host: "config1:27019" }]
  });
'

# === 3. Initialization Shard Dungeon Collection ===
mongosh --port 27018 --eval '
  rs.initiate({ _id: "shard1ReplSet", members: [{ _id: 0, host: "shard1a:27018" }] });
'

mongosh --port 27020 --eval '
  rs.initiate({ _id: "shard2ReplSet", members: [{ _id: 0, host: "shard2a:27020" }] });
'

# === 4. Through Mongos Add a shard ===
mongosh --port 27017 --eval '
  sh.addShard("shard1ReplSet/shard1a:27018");
  sh.addShard("shard2ReplSet/shard2a:27020");
'

# === 5. Enable Database Sharding ===
mongosh --port 27017 --eval '
  sh.enableSharding("shopdb");
  sh.shardCollection("shopdb.orders", { userId: 1, createdAt: -1 });  // Composite Segmented Key
'

# === 6. Insert Test Data(Automatically distributed across different shards)===
mongosh --port 27017 --eval '
  for (let i = 0; i < 10000; i++) {
    db.orders.insertOne({
      userId: "user_" + (i % 100),
      total: Math.random() * 1000,
      createdAt: new Date(),
      status: "paid"
    });
  }
'

# === 7. View Shard Distribution ===
mongosh --port 27017 --eval 'sh.status();'
# Output:
# shards:
#   { _id: 'shard1ReplSet', count: 5012 }
#   { _id: 'shard2ReplSet', count: 4988 }
# The data is evenly distributed across 2 shards

# === 8. When querying Mongos Automatic Routing ===
mongosh --port 27017 --eval '
  db.orders.find({ userId: "user_50" }).count();
'
# Mongos Automatically route to the corresponding shard(Based on userId Scope)
JAVASCRIPT
// === 9. App Connections Mongos(App Transparency,Transparent Sharding)===
const mongoose = require('mongoose');
await mongoose.connect('mongodb://localhost:27017/shopdb');
// No changes to the application code are required,Compared to a standalone system MongoDB Exactly the same

await Order.create({
  userId: 'user_001',
  total: 599,
  items: [{ sku: 'PHONE-001', qty: 1 }]
});
// Mongos Automatically route to the appropriate shard

// === 10. Hashed Sharding(Uniform Distribution of Data)===
mongosh --port 27017 --eval '
  sh.shardCollection("shopdb.products", { sku: "hashed" });
'
// sku Uniform Distribution After Hashing,Avoid Hot Spots

النتيجة: يتم توزيع 10,000 طلب تلقائيًا على شاردين (5,012 + 4,988)؛ ويتصل التطبيق عبر Mongos دون الحاجة إلى معرفة تفاصيل تقسيم البيانات إلى شاردات.


❓ أسئلة شائعة

س هل يمكنني استخدام فهرس فريد بعد تقسيم البيانات إلى شاردات؟
ج نعم، ولكن يجب أن يتضمن الفهرس الفريد مفتاح الشاردة (فهرس فريد مركب).
س هل يمكن تعديل مفتاح التجزئة؟
ج لا. بمجرد تعيين مفتاح التجزئة، لا يمكن تعديله (يجب إعادة إنشاء المجموعة).
س هل زيادة عدد الشاردات يُعد دائمًا أمرًا أفضل؟
ج لا. فوجود عدد كبير جدًّا من الشاردات يزيد من تعقيد العمليات. ونوصي باستخدام ما بين 3 و12 شاردة.
س هل ينبغي لنا استخدام Atlas أم إعداد شاردات خاصة بنا في بيئة الإنتاج؟
ج يُنصح باستخدام Atlas (مُدار + آلي). ولا يُنصح بإعداد شاردات خاصة إلا للشركات الكبيرة التي تمتلك فرقًا مخصصة لإدارة قواعد البيانات (DBA).

📖 ملخص


📝 تمارين

  1. الأسئلة الأساسية (⭐): فهم بنية التجزئة ومكوناتها (Mongo / خادم التكوين / الشارد).
  2. السؤال الأساسي (⭐): قم بتحليل سيناريو عملك وحدد ما إذا كان تقسيم البيانات (sharding) ضروريًا أم لا.
  3. تمرين متقدم (⭐⭐): قم بنشر مجموعة تحتوي على تكوين واحد وشاردين باستخدام Docker Compose.
  4. سؤال متقدم (⭐⭐): اختبار اختيار مفتاح التجزئة (userId مقابل sku مقابل المفتاح المركب).
  5. التحدي (⭐⭐⭐): نشر مجموعة مقسمة كاملة (مجموعة نسخ متماثلة للتكوين + مجموعتان من نسخ متماثلة للشرائح + Mongos + المراقبة).
Web-Tutorial.com

فريق Web-Tutorial التقني

منصة دروس برمجية يديرها عدة مطورين. كل درس يتم كتابته ومراجعته بواسطة مطورين متخصصين في المجال. نعمل على ضمان دقة وموثوقية المحتوى — إذا لاحظت أي مشكلة، فيرجى إخبارنا.

100%