أوضاع سعة DynamoDB: متى تختار On-Demand ومتى تختار Provisioned؟

عندما تبني تطبيقاً جديداً ولا تعرف بعد كيف سيتصرف حجم الطلبات، يصبح اختيار وضع السعة في DynamoDB قراراً حقيقياً وليس مجرد إعداد افتراضي — الاختيار الخاطئ يعني إما تقييداً مفاجئاً يُوقف التطبيق، أو فاتورة أعلى بكثير مما تتوقع.

ملخص سريع (TL;DR): أوضاع سعة DynamoDB

المعيار On-Demand Provisioned
أنماط حركة المرور غير معروفة أو متقلبة متوقعة ومستقرة
خطر التقييد منخفض جداً مرتفع إذا تجاوزت الحد المحجوز
التكلفة عند حجم ثابت أعلى أقل بشكل ملحوظ
التكلفة عند حجم منخفض أو صفري لا تدفع شيئاً تدفع للسعة المحجوزة حتى لو لم تُستخدم
Auto Scaling تلقائي بالكامل يتطلب تكوين Auto Scaling يدوياً
التبديل بين الوضعين مسموح مرة واحدة كل 24 ساعة

كيف تعمل أوضاع سعة DynamoDB

DynamoDB يقيس السعة بوحدتين أساسيتين: وحدة سعة القراءة (RCU) ووحدة سعة الكتابة (WCU). كل عملية قراءة أو كتابة تستهلك عدداً من هذه الوحدات بناءً على حجم العنصر ونوع العملية. الفرق الجوهري بين الوضعين هو من يتحكم في السقف.

في وضع Provisioned، أنت تحدد مسبقاً عدد RCUs وWCUs التي تريد تخصيصها. DynamoDB يحجز هذه السعة لجدولك. إذا تجاوزت الطلبات الحد المحجوز، يرفض الخدمة الطلبات الزائدة بخطأ ProvisionedThroughputExceededException. يمكنك تفعيل Auto Scaling لتعديل السعة تلقائياً، لكن هذا التعديل يستغرق وقتاً — ليس فورياً.

في وضع On-Demand، لا تحدد أي سعة مسبقاً. DynamoDB يتكيف تلقائياً مع حجم الطلبات الفعلي. تدفع فقط عن كل قراءة وكتابة تحدث فعلاً. الخدمة تستوعب ارتفاعات مفاجئة في حركة المرور دون تدخل منك، مع قيود موثقة على معدل الزيادة المفاجئة — راجع توثيق AWS لأحدث التفاصيل.

graph TD A["طلب قراءة/كتابة"] --> B["حساب RCU/WCU المستهلكة"] B --> C{"وضع السعة؟"} C -->|"Provisioned"| D["مقارنة مع السعة المحجوزة"] C -->|"On-Demand"| E["معالجة مباشرة"] D --> F{"ضمن الحد؟"} F -->|"نعم"| G["تنفيذ الطلب"] F -->|"لا"| H["ProvisionedThroughputExceededException"] E --> I["تنفيذ الطلب + احتساب للفوترة"] G --> J["CloudWatch: ConsumedCapacityUnits"] I --> J H --> K["CloudWatch: ThrottleEvents"]
  1. الطلب يصل إلى DynamoDB ويُحسب استهلاكه بوحدات RCU/WCU.
  2. في Provisioned: يُقارن الاستهلاك بالسعة المحجوزة — إذا تجاوزها يُرفض الطلب.
  3. في On-Demand: لا مقارنة مسبقة، الطلب يُعالج مباشرة ويُحتسب للفوترة.
  4. Auto Scaling في Provisioned يعمل بناءً على مقاييس CloudWatch ويعدّل السعة ضمن الحدود المضبوطة.

دليل القرار: أي وضع يناسب حالتك؟

قبل أن تختار، اسأل نفسك سؤالاً واحداً: هل تعرف كيف سيتصرف حجم الطلبات خلال الأسبوع القادم؟ إذا كانت الإجابة لا، فالقرار شبه محسوم.

graph TD Start(["هل تعرف أنماط حركة المرور؟"]) --> Q1{"الأنماط معروفة ومستقرة؟"} Q1 -->|"لا"| OD["On-Demand PAY_PER_REQUEST"] Q1 -->|"نعم"| Q2{"ارتفاعات مفاجئة غير متوقعة؟"} Q2 -->|"نعم"| OD Q2 -->|"لا"| Q3{"التكلفة الأولوية القصوى؟"} Q3 -->|"نعم"| PROV["Provisioned + Auto Scaling"] Q3 -->|"لا"| PROV OD --> MON["راقب CloudWatch لأسابيع"] MON --> EVAL{"أنماط واضحة ظهرت؟"} EVAL -->|"نعم"| SWITCH["قيّم الانتقال إلى Provisioned"] EVAL -->|"لا"| MON
  1. إذا كانت أنماط حركة المرور غير معروفة أو في مرحلة تطوير، On-Demand هو الخيار الأكثر أماناً.
  2. إذا كانت الأنماط متقلبة جداً مع ارتفاعات غير متوقعة، On-Demand يتجنب التقييد المفاجئ.
  3. إذا كانت الأنماط مستقرة ومتوقعة، Provisioned مع Auto Scaling يوفر تكلفة أقل على المدى الطويل.
  4. إذا كانت التكلفة هي الأولوية القصوى مع حجم ثابت ومعروف، Provisioned مع Reserved Capacity يعطي أفضل سعر.

الوضع الأول: On-Demand — الخيار الافتراضي للمجهول

عندما تبدأ مشروعاً جديداً أو تطلق ميزة لأول مرة، On-Demand هو الخيار العملي. لا تحتاج إلى تخمين السعة، ولا تخاطر بتقييد يُوقف تجربة المستخدم الأولى.

إنشاء جدول بوضع On-Demand

aws dynamodb create-table \
  --table-name MyAppTable \
  --attribute-definitions \
      AttributeName=PK,AttributeType=S \
      AttributeName=SK,AttributeType=S \
  --key-schema \
      AttributeName=PK,KeyType=HASH \
      AttributeName=SK,KeyType=RANGE \
  --billing-mode PAY_PER_REQUEST \
  --region us-east-1

تحويل جدول قائم إلى On-Demand

aws dynamodb update-table \
  --table-name MyAppTable \
  --billing-mode PAY_PER_REQUEST \
  --region us-east-1

تذكر: التبديل بين الوضعين مسموح مرة واحدة فقط كل 24 ساعة. لا تبدّل الوضع وأنت تحت ضغط حادثة إنتاجية — خطط لذلك مسبقاً.

التحقق من الوضع الحالي للجدول

aws dynamodb describe-table \
  --table-name MyAppTable \
  --query 'Table.BillingModeSummary' \
  --region us-east-1

الوضع الثاني: Provisioned — الخيار الاقتصادي للأنماط المعروفة

بعد أسابيع أو أشهر من تشغيل التطبيق، ستبدأ ترى أنماطاً واضحة في CloudWatch. في هذه اللحظة، التحول إلى Provisioned مع Auto Scaling يمكن أن يخفض التكلفة بشكل ملحوظ مقارنة بـ On-Demand.

إنشاء جدول بوضع Provisioned مع Auto Scaling

🔽 انقر لعرض أوامر CLI الكاملة
# الخطوة 1: إنشاء الجدول بسعة محددة
aws dynamodb create-table \
  --table-name MyAppTable \
  --attribute-definitions \
      AttributeName=PK,AttributeType=S \
      AttributeName=SK,AttributeType=S \
  --key-schema \
      AttributeName=PK,KeyType=HASH \
      AttributeName=SK,KeyType=RANGE \
  --billing-mode PROVISIONED \
  --provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \
  --region us-east-1

# الخطوة 2: تسجيل الجدول كهدف قابل للتوسع (للكتابة)
aws application-autoscaling register-scalable-target \
  --service-namespace dynamodb \
  --resource-id 'table/MyAppTable' \
  --scalable-dimension 'dynamodb:table:WriteCapacityUnits' \
  --min-capacity 5 \
  --max-capacity 100 \
  --region us-east-1

# الخطوة 3: تسجيل الجدول كهدف قابل للتوسع (للقراءة)
aws application-autoscaling register-scalable-target \
  --service-namespace dynamodb \
  --resource-id 'table/MyAppTable' \
  --scalable-dimension 'dynamodb:table:ReadCapacityUnits' \
  --min-capacity 5 \
  --max-capacity 100 \
  --region us-east-1

# الخطوة 4: تطبيق سياسة التوسع التلقائي للكتابة
aws application-autoscaling put-scaling-policy \
  --service-namespace dynamodb \
  --resource-id 'table/MyAppTable' \
  --scalable-dimension 'dynamodb:table:WriteCapacityUnits' \
  --policy-name 'MyAppTable-WriteAutoScaling' \
  --policy-type TargetTrackingScaling \
  --target-tracking-scaling-policy-configuration \
      'TargetValue=70.0,PredefinedMetricSpecification={PredefinedMetricType=DynamoDBWriteCapacityUtilization}' \
  --region us-east-1

القيمة TargetValue=70.0 تعني أن Auto Scaling يحاول الحفاظ على استخدام السعة عند 70%. هذا يترك هامشاً لاستيعاب الارتفاعات المفاجئة قبل أن يكتمل التوسع.

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

مراقبة التقييد في DynamoDB

سواء اخترت أي وضع، مراقبة مقاييس التقييد في CloudWatch ضرورية. مقياس ConsumedReadCapacityUnits وConsumedWriteCapacityUnits يُظهران الاستهلاك الفعلي، بينما ReadThrottleEvents وWriteThrottleEvents يُظهران حوادث التقييد.

فحص أحداث التقييد خلال آخر ساعة

aws cloudwatch get-metric-statistics \
  --namespace AWS/DynamoDB \
  --metric-name WriteThrottleEvents \
  --dimensions Name=TableName,Value=MyAppTable \
  --start-time $(date -u -d '1 hour ago' +%Y-%m-%dT%H:%M:%SZ) \
  --end-time $(date -u +%Y-%m-%dT%H:%M:%SZ) \
  --period 1800 \
  --statistics Sum \
  --region us-east-1

المعامل --period 1800 يجمع البيانات خلال نافذة مدتها 30 دقيقة، وهو ما يتوافق مع الطريقة التي تُجمّع بها CloudWatch مقاييس DynamoDB في هذا السياق. استخدم هذه النافذة كنقطة بداية لتحليل أنماط التقييد.

إنشاء تنبيه على أحداث التقييد

aws cloudwatch put-metric-alarm \
  --alarm-name DynamoDB-WriteThrottle-MyAppTable \
  --alarm-description 'تنبيه عند حدوث تقييد في الكتابة' \
  --namespace AWS/DynamoDB \
  --metric-name WriteThrottleEvents \
  --dimensions Name=TableName,Value=MyAppTable \
  --statistic Sum \
  --period 300 \
  --threshold 10 \
  --comparison-operator GreaterThanOrEqualToThreshold \
  --evaluation-periods 1 \
  --alarm-actions arn:aws:sns:us-east-1:123456789012:MyAlertTopic \
  --region us-east-1

تجربة حقيقية: التشخيص الخاطئ الذي يضيع الوقت

سيناريو شائع: التطبيق يُعيد أخطاء متقطعة، السجلات تُظهر ProvisionedThroughputExceededException، والمهندس يذهب مباشرة لرفع السعة المحجوزة. يرفعها من 100 إلى 500 WCU. الأخطاء تستمر.

التشخيص الخاطئ: 'السعة الإجمالية غير كافية.' الواقع: المشكلة في توزيع الطلبات على partitions، وليس في إجمالي السعة. مفتاح partition واحد يستقبل 80% من الكتابات — وهو ما يُسمى 'hot partition'. رفع السعة الإجمالية لا يُوزعها بشكل أفضل على نفس المفتاح الساخن.

الحل الفعلي: مراجعة تصميم مفتاح الـ partition لضمان توزيع أكثر اتزاناً، أو استخدام تقنية 'write sharding' بإضافة لاحقة عشوائية للمفتاح. رفع السعة وحده لا يحل مشكلة التوزيع غير المتوازن.

graph LR Req["طلبات الكتابة"] --> P1["Partition A
80% من الطلبات"] Req --> P2["Partition B
10% من الطلبات"] Req --> P3["Partition C
10% من الطلبات"] P1 --> TH["تقييد موضعي
Hot Partition"] P2 --> OK1["معالجة طبيعية"] P3 --> OK2["معالجة طبيعية"] TH --> ERR["ProvisionedThroughputExceededException"] style P1 fill:#ff6b6b,color:#fff style TH fill:#ff4444,color:#fff style ERR fill:#cc0000,color:#fff
  1. الطلبات تتركز على مفتاح partition واحد بدلاً من التوزيع المتساوي.
  2. السعة المحجوزة للجدول كافية إجمالاً، لكن السعة لكل partition لها حد خاص بها.
  3. رفع WCU الإجمالي لا يُغير توزيع الطلبات على نفس المفتاح الساخن.
  4. الحل الصحيح هو تحسين تصميم مفتاح الـ partition لضمان توزيع متوازن.

صلاحيات IAM المطلوبة لإدارة أوضاع السعة

لتنفيذ الأوامر الواردة في هذا المقال، الدور أو المستخدم يحتاج على الأقل الصلاحيات التالية:

🔽 عرض سياسة IAM المطلوبة
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DynamoDBTableManagement",
      "Effect": "Allow",
      "Action": [
        "dynamodb:CreateTable",
        "dynamodb:UpdateTable",
        "dynamodb:DescribeTable"
      ],
      "Resource": "arn:aws:dynamodb:us-east-1:123456789012:table/MyAppTable"
    },
    {
      "Sid": "AutoScalingManagement",
      "Effect": "Allow",
      "Action": [
        "application-autoscaling:RegisterScalableTarget",
        "application-autoscaling:PutScalingPolicy",
        "application-autoscaling:DescribeScalableTargets",
        "application-autoscaling:DescribeScalingPolicies"
      ],
      "Resource": "*"
    },
    {
      "Sid": "CloudWatchMonitoring",
      "Effect": "Allow",
      "Action": [
        "cloudwatch:GetMetricStatistics",
        "cloudwatch:PutMetricAlarm"
      ],
      "Resource": "*"
    }
  ]
}

لاحظ أن application-autoscaling وcloudwatch يتطلبان Resource: * لعمليات القراءة والوصف — هذا سلوك موثق في مرجع AWS Service Authorization.

متى تنتقل من On-Demand إلى Provisioned؟

السؤال الأصح ليس 'أيهما أفضل؟' بل 'متى أنتقل؟'. On-Demand هو نقطة البداية الطبيعية. بعد أسابيع من التشغيل، راجع مقاييس CloudWatch وابحث عن:

  • استقرار نسبي في ConsumedWriteCapacityUnits وConsumedReadCapacityUnits عبر الزمن.
  • غياب ارتفاعات مفاجئة كبيرة تتجاوز 2-3 أضعاف المتوسط.
  • نمط يومي أو أسبوعي واضح يمكن التنبؤ به.

إذا توفرت هذه المؤشرات، احسب تكلفة Provisioned مع Auto Scaling مقارنة بفاتورة On-Demand الحالية. في كثير من الحالات، الفرق يكون ملموساً عند حجم ثابت.

الخلاصة والخطوات التالية لاختيار وضع سعة DynamoDB

إذا كنت لا تعرف أنماط حركة المرور بعد، ابدأ بـ On-Demand — هذا ليس تردداً، بل قرار هندسي سليم. راقب الاستهلاك الفعلي عبر CloudWatch، وبعد أن تتضح الأنماط، قيّم الانتقال إلى Provisioned مع Auto Scaling لتحسين التكلفة.

الخطوات العملية الفورية:

  • راجع توثيق AWS الرسمي لأوضاع السعة للاطلاع على أحدث التفاصيل والقيود.
  • فعّل تنبيهات CloudWatch على WriteThrottleEvents وReadThrottleEvents من اليوم الأول.
  • راجع تصميم مفاتيح الـ partition قبل أي قرار برفع السعة.
  • استخدم حاسبة تسعير AWS لمقارنة التكلفة بين الوضعين بناءً على بياناتك الفعلية.

مسرد المصطلحات

المصطلح التعريف
RCU (Read Capacity Unit) وحدة سعة القراءة — تقيس استهلاك عمليات القراءة في DynamoDB
WCU (Write Capacity Unit) وحدة سعة الكتابة — تقيس استهلاك عمليات الكتابة في DynamoDB
Throttling (التقييد) رفض DynamoDB لطلبات تتجاوز السعة المتاحة بإعادة خطأ ProvisionedThroughputExceededException
Hot Partition مفتاح partition يستقبل نسبة غير متناسبة من الطلبات مما يسبب تقييداً موضعياً
Auto Scaling خدمة Application Auto Scaling التي تعدّل سعة Provisioned تلقائياً بناءً على مقاييس CloudWatch

تعليقات

المشاركات الشائعة من هذه المدونة

استرجاع معرّف نسخة EC2 عبر خدمة البيانات الوصفية IMDSv2

فهم مهلة الرؤية في SQS: لماذا تُعالَج رسائلك مرتين؟