اتساق البيانات والنسخ

الاتساق القوي والنصاب

18 دقيقة الدرس 4 من 10

الاتساق القوي والنصاب

الاتساق التدريجي أداةٌ عملية، لكنَّ بعض العمليات لا تتحمَّل أي قراءة قديمة. فالتحويل البنكي، وحجز المخزون، أو القفل الموزَّع — يجب أن تعكس آخر حالة مُثبَّتة في كل استعلام. الاتساق القوي يضمن ذلك تماماً: كل قراءة تُشاهد آخر كتابة ناجحة، أياً كان العقدة التي تسألها. والسؤال: كيف يتحقَّق ذلك عبر مجموعة من N نسخة دون اشتراط أن تكون كل العقد تعمل؟

مفهوم النصاب (Quorum)

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

  • W — عدد العقد التي يجب أن تُقرَّ الكتابة قبل أن يُعيد المنسِّق الاستجابة للعميل.
  • R — عدد العقد التي يجب أن تستجيب للقراءة قبل إعادة القيمة.

يحتوي الكتلة على N نسخة إجمالاً. والقاعدة الذهبية هي:

W + R > N — يجب أن يتقاطع مجموعة الكتابة ومجموعة القراءة في عقدة واحدة على الأقل. تلك العقدة المشتركة تحمل أحدث البيانات، مما يضمن حصول العميل عليها.

الاختيار الشائع في الإنتاج لـN = 5 هو W = 3، R = 3 (W + R = 6 > 5). إذ إن 3 عقد أقرَّت الكتابة و3 عقد تُستعلَم عند القراءة، فلا بد أن عقدة واحدة على الأقل موجودة في كلتا المجموعتين.

لماذا يضمن التقاطع الحداثة؟

افترض أنك كتبت القيمة v2 إلى العقد A وB وC (W = 3). لاحقاً، تستعلم قراءة من العقد A وD وE (R = 3). العقدة A في المجموعتين؛ فترجع v2. يختار المنسِّق القيمة ذات أعلى ختم إصدار، فيحصل العميل دائماً على v2 — وليس القيمة القديمة v1 التي تعرفها D وE فحسب.

Quorum Overlap: W=3 write nodes and R=3 read nodes share node A, guaranteeing the fresh value is returned Write (W=3) Read (R=3) Node A Node B Node C Node D Node E Coordinator Write(v2) v2 v2 v2 Coordinator Read Overlap (fresh v2) has v1 has v1 has v2 N=5 replicas | W=3 | R=3 | W+R=6 > 5 ✓ Node A is in both the write set and read set — freshness guaranteed
مع N=5 وW=3 وR=3، تكون العقدة A دائماً في كلتا المجموعتين. يختار المنسِّق القيمة الأحدث إصداراً ويُعيدها للعميل.

إعدادات النصاب الشائعة

تتيح مجموعات مختلفة من W وR التوازن بين زمن الاستجابة والاتساق، طالما يتحقق W + R > N:

  • القراءة الكثيفة (W=N، R=1): يجب أن تُقرَّ الكتابة من جميع العقد (كتابة بطيئة)، لكن أي عقدة واحدة تكفي للقراءة (قراءة سريعة). يُستخدم حين تفوق القراءات الكتابات بفارق كبير.
  • الكتابة الكثيفة (W=1، R=N): تُعترَف بالكتابة فوراً من عقدة واحدة، لكن القراءة تحتاج جميع العقد. نادر التطبيق عملياً.
  • المتوازن (W = R = ⌈(N+1)/2⌉): الإعداد الأكثر شيوعاً. لـN=5، كلاهما يساوي 3. يتحمَّل فشل ما يصل إلى N−W عقدة في الكتابات وN−R في القراءات.

النصاب المرن والتسليم الموعود

حين تكون بعض العقد غير متاحة مؤقتاً، سيرفض النصاب الصارم الكتابة ويُعيد خطأً للعميل. تُطبِّق بعض الأنظمة (DynamoDB، Cassandra) نصاباً مرناً: إذا كانت النسخة المستهدفة معطَّلة، تقبل عقدة صحيحة مختلفة الكتابة مؤقتاً مع تخزين "تلميح" لإعادة التوجيه حين تعود العقدة الأصلية. يُبقي ذلك الكتابات متاحة على حساب إضعاف ضمان الاتساق مؤقتاً.

النصاب المرن لا يضمن الاتساق القوي. إذا كنت بحاجة إلى خطية صارمة، عطِّل النصاب المرن واقبل المقايضة في التوافر. نظرية CAP ليست قابلة للتفاوض: أنت تختار الاتساق على حساب التوافر خلال التقطيع.

متجهات الإصدار وحل التعارضات

في قراءة النصاب، قد تُعيد نسخ متعددة إصدارات مختلفة للمفتاح ذاته. يجب أن يختار المنسِّق الفائز. ثمة استراتيجيتان:

  1. آخر كتابة تفوز (LWW): تحمل كل قيمة طابعاً زمنياً أو عداداً تصاعدياً. الأعلى يفوز. بسيطة، لكن انحراف الساعات في العقد الموزعة قد يؤدي إلى حذف كتابة جديدة صالحة.
  2. متجهات الإصدار: تحتفظ كل عقدة بعداد خاص بها لكل نسخة. يدمج المنسِّق المتجهات ويكتشف التعارضات الحقيقية (الكتابات المتزامنة). يحلَّها التطبيق (عبر CRDTs أو المستخدم). تستخدمه أنظمة مثل Riak ووضع متجه الساعة في DynamoDB.

التطبيقات الفعلية

Quorum settings in Apache Cassandra: replication factor, consistency levels, and the resulting W+R guarantee System N (Replication Factor) W / R Setting W + R > N? Cassandra QUORUM 3 W=2, R=2 4 > 3 ✓ Cassandra ALL 3 W=3, R=3 6 > 3 ✓ (strict) DynamoDB Strong Read 3 W=2, R=2 4 > 3 ✓ DynamoDB Eventual Read 3 W=2, R=1 3 = 3 ✗ (eventual) etcd (Raft-based) 5 W=3, R=3 6 > 5 ✓ يجب أن يتجاوز W + R القيمة N لضمان التقاطع. التساوي (W+R=N) غير كافٍ — عقدة واحدة مفقودة تكسر الحداثة.
إعدادات النصاب في الأنظمة الموزعة الشائعة. فقط الإعدادات التي يكون فيها W + R > N تضمن قراءات قوية (خطية).

في Apache Cassandra، تحدد عامل النسخ على مستوى الـkeyspace ومستوى الاتساق في كل استعلام. CONSISTENCY QUORUM على الكتابات والقراءات مع RF=3 يعطي W=2، R=2، محققاً W + R = 4 > 3. بينما يتطلب CONSISTENCY ALL جميع النسخ، مما يُزيل القِدَم لكنه يُقلِّل التوافر.

يستخدم etcd، مخزن إعدادات Kubernetes، خوارزمية Raft داخلياً. Raft في جوهرها بروتوكول نصاب: يجب على القائد استلام إقرارات من أغلبية العقد قبل تثبيت أي إدخال. مع خمس عقد etcd، يحتاج القائد إلى ثلاثة (الأغلبية) — مطابق تماماً لنصاب W=3 من أصل N=5.

زمن الاستجابة مقابل الاتساق

التكلفة الجوهرية للنصاب الصارم هي زمن الاستجابة. لا تُعيد الكتابة نتيجة حتى تستجيب W نسخ، والقراءة تنتظر R نسخ. إذا كانت إحدى تلك النسخ في منطقة توافر مختلفة تضيف 20 مللي ثانية، فسيُهيمن P99 للكتابة على أبطأ الإقرارات. ولهذا يُعدُّ ضبط W وR قراراً تجارياً: سلة التسوق تتحمل الاتساق التدريجي (زمن أقل، توافر أعلى)، بينما دفتر الأستاذ المالي يستدعي النصاب الصارم (زمن أعلى، صواب مطلق).

نصيحة تصميم: ابدأ بـN=3، W=2، R=2. هذه النقطة المثالية لمعظم قواعد البيانات: تتحمل فشل عقدة واحدة في الكتابات والقراءات، وتضيف تكلفة شبكية بسيطة، وتُحقق قاعدة النصاب بمريحة (4 > 3).

النصاب ليس حلاً سحرياً

حتى مع W + R > N، لا يكون الخطي (Linearizability) تلقائياً. في حال تسابق كتابتين متزامنتين، قد يرى المنسِّق قيماً مختلفة من عقد مختلفة في الجولة القرائية ذاتها. الأنظمة التي تحتاج إلى خطية حقيقية — دون أي حالات شاذة — يجب أن تُضيف بروتوكول توافق (Raft أو Paxos) فوق النصاب. النصاب وحده يضمن فقط أن الكتابة المُثبَّتة بالكامل مرئية، لا أن الكتابات المتزامنة مُرتَّبة بشكل صحيح. نتناول Raft وPaxos في الدرس السابع.

ملخص: يُفرض الاتساق القوي بالنصاب عبر ضمان تقاطع مجموعة الكتابة ومجموعة القراءة في عقدة واحدة على الأقل. قاعدة W + R > N تجعل هذا التقاطع مضموناً رياضياً. يتيح ضبط W وR الانزلاق على طيف زمن الاستجابة مقابل الاتساق، مع البقاء فوق عتبة الاتساق القوي.