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

النسخ المتماثل متعدد القادة وعديم القادة

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

النسخ المتماثل متعدد القادة وعديم القادة

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

النسخ متعدد القادة

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

من الأنظمة الحقيقية التي تعتمد هذا النمط: CockroachDB (متعدد المناطق)، وMySQL Group Replication، وPostgreSQL BDR، وGoogle Docs (لتحرير المستندات بشكل تعاوني).

المزايا:

  • زمن استجابة كتابة منخفض محلياً — تكتب كل منطقة إلى قائدها القريب دون رحلة عبر القارات.
  • يستمر قبول الكتابات حتى لو أُغلق مركز بيانات بأكمله.
  • إنتاجية الكتابة تتوسع أفقياً: قائدان يضاعفان تقريباً طاقة الكتابة.

الثمن: تعارضات الكتابة. إذا قَبِل قائدان كتابتين مختلفتين على نفس السجل في الوقت ذاته، نشأ تعارض يجب حلّه. هذا هو التحدي المحوري في الأنظمة متعددة القادة.

استراتيجيات حل التعارض

لا توجد إجابة صحيحة واحدة؛ تختار بحسب دلالات البيانات:

  • آخر كتابة تفوز (LWW): إرفاق طابع زمني بكل كتابة والاحتفاظ بأعلى قيمة. بسيط لكن خطير — تختلف ساعات الأجهزة الموزعة، فقد تُهمَل التحديثات الحقيقية. تعتمده Cassandra افتراضياً.
  • منطق الدمج المخصص: يُعرّف التطبيق معنى "الدمج". قد تضم سلة التسوق العناصر من كلا النسختين. يُرسّخ CRDT (نوع البيانات المُتماثل بلا تعارض) هذا في هياكل بيانات تُنتج دائماً نفس النتيجة بصرف النظر عن ترتيب التطبيق.
  • الكشف أثناء الكتابة أو القراءة: اكتشاف التعارض عند الكتابة ورفضه أو تأجيله، أو تخزين كل النسخ المتعارضة وحلّها عند القراءة التالية (نموذج سلة تسوق Amazon).
النسخ متعدد القادة صعب التطبيق الصحيح. حتى قواعد البيانات التي تُعلن دعم التعدد كثيراً ما تحتوي أخطاء دقيقة في حل التعارض. إن أمكنك تجنّبه — مثلاً بتقسيم الكتابات بحيث يكون لكل قسم قائد واحد — فافعل. لا تلجأ إليه إلا حين تحتاج فعلاً إلى زمن استجابة أقل من 10 ميلي ثانية للكتابة من قارات متعددة، أو حين تتجاوز الكتابات طاقة جهاز واحد.
Multi-leader replication across two data centers Data Center — US East Data Center — EU West Client (US) WRITE request Leader (US) Accepts WRITEs locally Follower (US) Read Replica Client (EU) WRITE request Leader (EU) Accepts WRITEs locally Follower (EU) Read Replica async replication ⚡ conflict possible
إعداد متعدد القادة بين مركزَي بيانات: يقبل كل قائد الكتابات محلياً ويُرسلها بشكل غير متزامن للآخر. الكتابات المتزامنة على نفس السجل تُفضي إلى تعارض يحتاج حلاً.

النسخ عديم القادة — نموذج Dynamo

اقترحت ورقة Dynamo من Amazon (2007) — والأنظمة مفتوحة المصدر المستوحاة منها، وفي مقدمتها Apache Cassandra وRiak — مقاربة مختلفة جذرياً: إلغاء مفهوم القائد كلياً. يمكن لأي نسخة قبول أي عملية كتابة. تُرسَل القراءات إلى عدة نسخ في آنٍ واحد، ويتولى العميل (أو عقدة منسّقة) التوفيق بين الاختلافات.

الرياضيات التي تُتيح ذلك هي قواعد النصاب (Quorum). لعنقود من N نسخ:

  • تُرسَل كل كتابة إلى W نسخ؛ وتنجح حين تُؤكّد W نسخ استلامها.
  • تُرسَل كل قراءة إلى R نسخ؛ ويأخذ العميل القيمة الأحدث.
  • إذا تحقق W + R > N، فستكون إحدى النسخ مشتركة بين مجموعة الكتابة ومجموعة القراءة، مما يضمن أن القراءة ترى آخر كتابة.

الإعداد الشائع في الإنتاج هو N=3, W=2, R=2. يتحمل هذا الإعداد تعطّل نسخة واحدة للقراءة والكتابة (إذ تكفي 2 من 3). للميل نحو التوفر، استخدم W=1, R=1 (سريع لكن القراءات قد تكون قديمة). للميل نحو الاتساق، استخدم W=3, R=1 (كل كتابة مُؤكَّدة من جميع النسخ — أبطأ، لكن القراءات دائماً حديثة).

النصاب لا يضمن الاتساق القوي في جميع الحالات. يمكن للأعطال الشبكية أن تُنشئ "نصاباً فضفاضاً" (تكتب Cassandra إلى العقد المتاحة خارج المجموعة المفضّلة عبر Hinted Handoff)، وقد تُفضي الكتابات المتزامنة إلى تعارضات في النسخ. تُوفّر الأنظمة عديمة القادة عادةً اتساقاً نهائياً مع ضمانات قابلة للضبط، لا اتساقاً صارماً.

إصلاح القراءة ومكافحة الانحراف

حين يقرأ النظام عديم القادة من R نسخ ويجد بعضها متأخراً، يُصلحها فوراً: يكتب المنسّق النسخة الأحدث إلى النسخ المتأخرة قبل إعادة الإجابة للعميل، وهو ما يُعرف بـإصلاح القراءة (Read Repair). كذلك تعمل عملية مكافحة الانحراف (Anti-Entropy) في الخلفية على مقارنة النسخ باستمرار باستخدام شجرة Merkle (شجرة تجزئة لأقسام البيانات) ومزامنة أي انحراف، حتى للبيانات التي لا يقرأها أحد. يضمن كلاهما معاً تقارب النسخ حتى بعد انقطاعات مطوّلة.

متجهات الإصدار وكشف التعارض

كيف يعرف النظام أيّ القيمتين المتعارضتين أحدث؟ لا يمكن الاعتماد على وقت الساعة الجدارية وحده. بدلاً من ذلك، تحمل كل قيمة متجه إصدار (Version Vector) (خريطة من معرّف العقدة إلى رقم تسلسلي، مشابهة لساعة المتجه). حين يحدث تعارض بين كتابتين غير متزامنتين على عقدتين مختلفتين ولا يتفوق أي متجه على الآخر، فهما أخوان تعارضيان يجب أن يحلّهما التطبيق (عادةً بدالة دمج أو CRDT). حين يهيمن أحد المتجهين على الآخر، يكون الأعلى هو الأحدث حتماً.

Leaderless quorum write and read repair (N=3, W=2, R=2) Client WRITE v=42 Coordinator routes to N=3 nodes Replica A ✓ v=42 written ACK → coordinator Replica B ✓ v=42 written ACK → coordinator Replica C ✗ unreachable hinted handoff queued W=2 quorum met → client SUCCESS Read Repair: synced on next read N = 3 replicas | W = 2 | R = 2 → W+R > N ✓
كتابة بنصاب عديم القادة مع N=3، W=2: يُرسل المنسّق الكتابة إلى الثلاث نسخ؛ تأكيدان يُحقّقان النصاب وينجح طلب العميل. تُصلَح النسخة C بشكل غير متزامن.

متعدد القادة مقابل عديم القادة: متى تختار كلاً منهما؟

كلا النمطين يُضحّيان بالبساطة لصالح التوسع. الاختيار الصحيح يعتمد على قيدك الأساسي:

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