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

النسخ المتماثل: القائد والأتباع

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

النسخ المتماثل: القائد والأتباع

كل قاعدة بيانات يجب أن تصمد أمام أعطال الأجهزة تحتاج إلى نسختين على الأقل من بياناتها. النسخ المتماثل من نوع القائد والأتباع — المعروف أيضاً بـ النسخة الأساسية والنسخ المتطابقة أو Master-Slave — هو أكثر استراتيجيات تحقيق ذلك انتشاراً. تستقبل عقدة واحدة، وهي القائد، جميع عمليات الكتابة. بينما تتلقى عقدة أو أكثر من الأتباع تدفقاً مستمراً من التغييرات قادماً من القائد، وتحافظ كل منها على نسخة محدّثة من البيانات. يمكن تلبية طلبات القراءة من أي عقدة في المجموعة.

تتبنى أنظمة مثل PostgreSQL وMySQL وMongoDB وRedis وKafka وعشرات غيرها هذا النمط كميزة أساسية. إن فهم آلية عمله — ومعرفة نقاط انهياره — أمر جوهري لأي مهندس يصمم أنظمة على نطاق واسع.

كيف يعمل النسخ المتماثل

عندما تصل عملية كتابة إلى القائد، يُضيفها إلى سجل دائم ومرتّب يُسمى Write-Ahead Log (WAL) في PostgreSQL أو Binary Log (binlog) في MySQL. يحتفظ كل تابع باتصال دائم مع القائد ويستقبل هذا السجل بشكل متواصل، ثم يُعيد تطبيق نفس العمليات بنفس الترتيب، مما يضمن أن نسختهم المحلية تتقارب تدريجياً لتصبح مطابقة لنسخة القائد.

Leader-Follower Replication — Write and Read Paths Client Write Leader (Primary) Accepts all writes · WAL/binlog Replication Replication Follower 1 Replica · Read traffic Follower 2 Replica · Read traffic Read Read
تذهب عمليات الكتابة دائماً إلى القائد؛ يبث القائد التغييرات إلى الأتباع عبر WAL/binlog؛ بينما يمكن تلبية القراءات من أي عقدة.

النسخ المتزامن مقابل النسخ غير المتزامن

الخيار التصميمي الجوهري في أي إعداد قائد-أتباع هو متى يعتبر القائد عملية الكتابة مكتملة. ثمة وضعان أساسيان:

النسخ المتزامن

ينتظر القائد حتى يُقرّ تابع واحد على الأقل بأنه كتب التغيير في تخزين دائم، ثم يُعيد النجاح إلى العميل.

  • الضمان: إذا أُصيب القائد بعطل فوري عقب الكتابة، فإن التابع المتزامن المحدد لديه نسخة كاملة ومحدّثة. لا فقدان للبيانات عند تعطل القائد.
  • التكلفة: كل عملية كتابة تستلزم الآن رحلة شبكية كاملة ذهاباً وإياباً إلى التابع. إذا كان التابع في مركز بيانات آخر على بُعد 50 مللي ثانية، فستتأخر كل عملية كتابة 100 مللي ثانية على الأقل. وإذا تعطل التابع المتزامن، تتوقف عمليات الكتابة بالكامل حتى استعادته أو إعادة الإعداد.

مثال واقعي: تتيح PostgreSQL الإشارة إلى نسخ متطابقة بعينها عبر synchronous_standby_names. يستخدم AWS RDS Multi-AZ النسخ المتزامن إلى النسخة الاحتياطية — تُحجب عمليات الكتابة حتى تُقرّ النسخة الاحتياطية باستلامها. لذلك يمتلك RDS Multi-AZ زمن استجابة أعلى قليلاً في الكتابة مقارنةً بالنشر في منطقة واحدة، لكنه يضمن RPO (هدف نقطة الاسترداد) يساوي صفراً.

النسخ غير المتزامن

يكتب القائد إلى تخزينه الدائم المحلي ويُعيد النجاح للعميل فوراً دون انتظار أي تابع. يُشحن سجل النسخ المتماثل إلى الأتباع في الخلفية، وعادةً خلال أجزاء من الثانية.

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

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

Synchronous vs Asynchronous Replication — Comparison Synchronous Replication Client Leader Follower 1. Write 2. Replicate 3. ACK 4. OK Zero data loss on leader crash Higher write latency (+RTT) Writes block if follower is down Asynchronous Replication Client Leader Follower 1. Write 2. OK 3. Later... Low write latency (local disk only) Possible data loss on leader crash Followers stay up independently
النسخ المتزامن ينتظر تأكيد التابع قبل تأكيد الكتابة؛ بينما النسخ غير المتزامن يؤكد فوراً ويُشحن التغييرات في الخلفية.
النسخ شبه المتزامن (المستخدم في MySQL وGoogle Spanner) هو الحل الوسط العملي: ينتظر القائد تأكيد تابع واحد على الأقل فقط، بينما يظل بقية الأتباع غير متزامنين. تحصل على المتانة دون اشتراط أن تكون المجموعة بأكملها سليمة لكي تمضي عمليات الكتابة.

تأخر النسخ المتماثل: مصنع الأخطاء الصامتة

يُنشئ النسخ غير المتزامن فجوة زمنية تُعرف بـ تأخر النسخ المتماثل، تكون فيها بيانات التابع متأخرة قليلاً عن القائد. يُفرز هذا أخطاء تطبيقية مدهشة:

  • انتهاك "اقرأ ما كتبته": يرسل مستخدم تحديثاً لملفه الشخصي. تذهب الكتابة إلى القائد. بعد ثانية يُحدّث الصفحة؛ يوجَّه طلبه إلى تابع متأخر فيظهر الملف القديم. يظن المستخدم أن النموذج لم يعمل ويُرسله مرة أخرى محدثاً تكراراً.
  • انتهاك القراءة الرتيبة: يقرأ المستخدم عدد التعليقات من Follower 1 (تأخر 0 مللي ثانية) فيرى 42. يُحدّث الصفحة؛ يُوجَّه الطلب إلى Follower 2 (تأخر 800 مللي ثانية) فيُعاد 38. يبدو الوقت وكأنه يسير للخلف.
  • انتهاكات السببية: ينشر مستخدم سؤالاً؛ يرى مستخدم آخر رد مستخدم ثالث دون أن يرى السؤال الأصلي — الرد كان على القائد، والسؤال لا يزال في طريقه إلى التابع.
حلول لانتهاك "اقرأ ما كتبته": وجّه قراءات مستخدم بعينه إلى القائد لمدة ثانية على الأقل عقب أي كتابة من ذلك المستخدم، أو تتبع موضع سجل النسخ في كوكي وقدّم القراءات فقط من أتباع وصلوا إلى ذلك الموضع أو تخطّوه. كلا النهجين مستخدمان في الإنتاج على نطاق واسع.

التعافي من الأعطال: ترقية تابع إلى قائد

عند تعطل القائد، يجب على النظام انتخاب قائد جديد من بين الأتباع الناجين. تُسمى هذه العملية الفشل والتعافي (Failover)، وهنا يكون لوضع النسخ المتماثل أشد التداعيات.

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

اختيار القائد الجديد: التابع ذو سجل النسخ الأحدث هو الأكثر أماناً لتقليل فقدان البيانات. في المجموعات المُدارة تلقائياً (PostgreSQL Patroni، MySQL Group Replication، MongoDB replica sets)، تتولى خوارزمية انتخاب — غالباً مبنية على Raft الذي ستدرسه في الدرس السابع — هذا الاختيار.

خطر فقدان البيانات مع النسخ غير المتزامن: إذا كان القائد القديم يسبق جميع الأتباع بـ 50 كتابة لحظة تعطله، فتلك الخمسون كتابة اختفت نهائياً. والأخطر: إذا عاد القائد القديم للعمل (كان معزولاً شبكياً لا متوقفاً)، فلديه كتابات لا يعرفها القائد الجديد. يُنشئ هذا سيناريو الدماغ المنقسم (Split-Brain): عقدتان تعتقدان كلتاهما أنها القائد الموثوق.

لا تسمح أبداً بوجود قائدَين في آنٍ واحد. الدماغ المنقسم هو أحد أخطر أنماط الإخفاق في قواعد البيانات الموزعة. تستخدم أنظمة التعافي التلقائي تقنية تُسمى السياج (Fencing) أو STONITH (أُطلق النار على العقدة الأخرى في رأسها) لضمان تعطيل القائد القديم كلياً قبل أن يبدأ الجديد في قبول الكتابات. بدون السياج، سيُفسد الدماغ المنقسم البيانات بصمت.

توسيع نطاق القراءة ونموذج الطاقة الاستيعابية

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

  • تُشغّل ويكيبيديا عشرات النسخ المتطابقة من MariaDB حول العالم، وتُوجّه حركة القراء إلى الأقرب جغرافياً بينما تذهب جميع التعديلات إلى النسخة الأساسية.
  • يُقدّم Stack Overflow غالبية استعلاماته من النسخ المتطابقة، مُبقياً القائد للكتابات واستعلامات إبطال التخزين المؤقت.
  • معظم صفحات كتالوج المنتجات في التجارة الإلكترونية تُقرأ من النسخ المتطابقة؛ أما الدفع — وهو مسار كتابة — فيصل دائماً إلى القائد.
الأتباع لا يُساعدون في إنتاجية الكتابة. جميع عمليات الكتابة لا تزال تمر عبر قائد واحد. إذا كانت اختناقك في طاقة الكتابة (تسجيل أحداث بحجم كبير، استيعاب سلاسل زمنية، دفاتر حسابات مالية)، فالنسخ المتماثل قائد-أتباع وحده لا يُجدي — تحتاج إلى التقسيم (Sharding) أو نسخ متعدد القادة (الدرس 6) أو مخزن مُحسَّن للكتابة.

اختيار الإعداد المناسب

مصفوفة قرارات عملية:

  • RPO = 0، الكتابات تتحمل زمن استجابة أعلى: استخدم النسخ المتزامن إلى تابع واحد على الأقل. AWS RDS Multi-AZ وGoogle Cloud SQL HA وPostgreSQL مع synchronous_commit = on جميعها تُحقق هذا.
  • كتابة سريعة، يمكن تحمّل نافذة صغيرة من فقدان البيانات: نسخ غير متزامن مع تعافٍ تلقائي (Patroni، Orchestrator). اقبل أن التعافي قد يخسر ثواني قليلة من آخر الكتابات.
  • قراءات عبر مناطق جغرافية بزمن استجابة منخفض: نسخ متطابقة للقراءة غير متزامنة في كل منطقة. اقبل أن قراءات التابع عبر المناطق قد تكون قديمة قليلاً.
  • الحاجة إلى المتانة والسرعة معاً: نسخ شبه متزامن — تابع متزامن واحد في نفس مركز البيانات، والبقية غير متزامنين بما فيهم النسخ عبر المناطق.