النسخ المتماثل: القائد والأتباع
النسخ المتماثل: القائد والأتباع
كل قاعدة بيانات يجب أن تصمد أمام أعطال الأجهزة تحتاج إلى نسختين على الأقل من بياناتها. النسخ المتماثل من نوع القائد والأتباع — المعروف أيضاً بـ النسخة الأساسية والنسخ المتطابقة أو Master-Slave — هو أكثر استراتيجيات تحقيق ذلك انتشاراً. تستقبل عقدة واحدة، وهي القائد، جميع عمليات الكتابة. بينما تتلقى عقدة أو أكثر من الأتباع تدفقاً مستمراً من التغييرات قادماً من القائد، وتحافظ كل منها على نسخة محدّثة من البيانات. يمكن تلبية طلبات القراءة من أي عقدة في المجموعة.
تتبنى أنظمة مثل PostgreSQL وMySQL وMongoDB وRedis وKafka وعشرات غيرها هذا النمط كميزة أساسية. إن فهم آلية عمله — ومعرفة نقاط انهياره — أمر جوهري لأي مهندس يصمم أنظمة على نطاق واسع.
كيف يعمل النسخ المتماثل
عندما تصل عملية كتابة إلى القائد، يُضيفها إلى سجل دائم ومرتّب يُسمى Write-Ahead Log (WAL) في PostgreSQL أو Binary Log (binlog) في MySQL. يحتفظ كل تابع باتصال دائم مع القائد ويستقبل هذا السجل بشكل متواصل، ثم يُعيد تطبيق نفس العمليات بنفس الترتيب، مما يضمن أن نسختهم المحلية تتقارب تدريجياً لتصبح مطابقة لنسخة القائد.
النسخ المتزامن مقابل النسخ غير المتزامن
الخيار التصميمي الجوهري في أي إعداد قائد-أتباع هو متى يعتبر القائد عملية الكتابة مكتملة. ثمة وضعان أساسيان:
النسخ المتزامن
ينتظر القائد حتى يُقرّ تابع واحد على الأقل بأنه كتب التغيير في تخزين دائم، ثم يُعيد النجاح إلى العميل.
- الضمان: إذا أُصيب القائد بعطل فوري عقب الكتابة، فإن التابع المتزامن المحدد لديه نسخة كاملة ومحدّثة. لا فقدان للبيانات عند تعطل القائد.
- التكلفة: كل عملية كتابة تستلزم الآن رحلة شبكية كاملة ذهاباً وإياباً إلى التابع. إذا كان التابع في مركز بيانات آخر على بُعد 50 مللي ثانية، فستتأخر كل عملية كتابة 100 مللي ثانية على الأقل. وإذا تعطل التابع المتزامن، تتوقف عمليات الكتابة بالكامل حتى استعادته أو إعادة الإعداد.
مثال واقعي: تتيح PostgreSQL الإشارة إلى نسخ متطابقة بعينها عبر synchronous_standby_names. يستخدم AWS RDS Multi-AZ النسخ المتزامن إلى النسخة الاحتياطية — تُحجب عمليات الكتابة حتى تُقرّ النسخة الاحتياطية باستلامها. لذلك يمتلك RDS Multi-AZ زمن استجابة أعلى قليلاً في الكتابة مقارنةً بالنشر في منطقة واحدة، لكنه يضمن RPO (هدف نقطة الاسترداد) يساوي صفراً.
النسخ غير المتزامن
يكتب القائد إلى تخزينه الدائم المحلي ويُعيد النجاح للعميل فوراً دون انتظار أي تابع. يُشحن سجل النسخ المتماثل إلى الأتباع في الخلفية، وعادةً خلال أجزاء من الثانية.
- الميزة: تحدد زمن استجابة الكتابة القرص المحلي للقائد فقط. الأتباع في مناطق أخرى لا يُبطئون الكتابة أبداً.
- الخطر: تأخر النسخ المتماثل. إذا تعطل القائد قبل أن يُنسخ تابع لآخر بضع عمليات كتابة، فتلك الكتابات مفقودة نهائياً.
أرقام واقعية: في نشر صحي داخل مركز بيانات واحد، يكون تأخر النسخ المتماثل غير المتزامن في PostgreSQL أقل من 10 مللي ثانية عادةً. تحت الحمل الكبير أو عبر مناطق جغرافية مختلفة، قد يرتفع إلى مئات المللي ثوانٍ أو حتى ثوانٍ. أي قراءة من تابع متأخر قد ترجع بيانات قديمة — وهو سيناريو الاتساق النهائي الكلاسيكي.
تأخر النسخ المتماثل: مصنع الأخطاء الصامتة
يُنشئ النسخ غير المتزامن فجوة زمنية تُعرف بـ تأخر النسخ المتماثل، تكون فيها بيانات التابع متأخرة قليلاً عن القائد. يُفرز هذا أخطاء تطبيقية مدهشة:
- انتهاك "اقرأ ما كتبته": يرسل مستخدم تحديثاً لملفه الشخصي. تذهب الكتابة إلى القائد. بعد ثانية يُحدّث الصفحة؛ يوجَّه طلبه إلى تابع متأخر فيظهر الملف القديم. يظن المستخدم أن النموذج لم يعمل ويُرسله مرة أخرى محدثاً تكراراً.
- انتهاك القراءة الرتيبة: يقرأ المستخدم عدد التعليقات من Follower 1 (تأخر 0 مللي ثانية) فيرى 42. يُحدّث الصفحة؛ يُوجَّه الطلب إلى Follower 2 (تأخر 800 مللي ثانية) فيُعاد 38. يبدو الوقت وكأنه يسير للخلف.
- انتهاكات السببية: ينشر مستخدم سؤالاً؛ يرى مستخدم آخر رد مستخدم ثالث دون أن يرى السؤال الأصلي — الرد كان على القائد، والسؤال لا يزال في طريقه إلى التابع.
التعافي من الأعطال: ترقية تابع إلى قائد
عند تعطل القائد، يجب على النظام انتخاب قائد جديد من بين الأتباع الناجين. تُسمى هذه العملية الفشل والتعافي (Failover)، وهنا يكون لوضع النسخ المتماثل أشد التداعيات.
اكتشاف الإخفاق: تعتمد معظم الأنظمة على مهلة زمنية. إذا لم يُرسل القائد نبضة قلب خلال N ثانية (عادةً 10–30 ثانية)، يستنتج الأتباع أنه أُصيب بعطل. يجب ضبط هذه المهلة بعناية — قصيرة جداً تُسبب إنذارات كاذبة؛ طويلة جداً تعني توقفاً مطوّلاً.
اختيار القائد الجديد: التابع ذو سجل النسخ الأحدث هو الأكثر أماناً لتقليل فقدان البيانات. في المجموعات المُدارة تلقائياً (PostgreSQL Patroni، MySQL Group Replication، MongoDB replica sets)، تتولى خوارزمية انتخاب — غالباً مبنية على Raft الذي ستدرسه في الدرس السابع — هذا الاختيار.
خطر فقدان البيانات مع النسخ غير المتزامن: إذا كان القائد القديم يسبق جميع الأتباع بـ 50 كتابة لحظة تعطله، فتلك الخمسون كتابة اختفت نهائياً. والأخطر: إذا عاد القائد القديم للعمل (كان معزولاً شبكياً لا متوقفاً)، فلديه كتابات لا يعرفها القائد الجديد. يُنشئ هذا سيناريو الدماغ المنقسم (Split-Brain): عقدتان تعتقدان كلتاهما أنها القائد الموثوق.
توسيع نطاق القراءة ونموذج الطاقة الاستيعابية
أحد الدوافع الرئيسية للأتباع هو توسيع طاقة القراءة. إذا كان 95% من حركة مرورك قراءات، فإضافة ثلاث نسخ متطابقة للقراءة يُضاعف طاقتك ثلاث مرات دون أي تغيير على القائد. هذا هو النموذج الذي يعتمده تقريباً كل تطبيق ويب كبير:
- تُشغّل ويكيبيديا عشرات النسخ المتطابقة من MariaDB حول العالم، وتُوجّه حركة القراء إلى الأقرب جغرافياً بينما تذهب جميع التعديلات إلى النسخة الأساسية.
- يُقدّم Stack Overflow غالبية استعلاماته من النسخ المتطابقة، مُبقياً القائد للكتابات واستعلامات إبطال التخزين المؤقت.
- معظم صفحات كتالوج المنتجات في التجارة الإلكترونية تُقرأ من النسخ المتطابقة؛ أما الدفع — وهو مسار كتابة — فيصل دائماً إلى القائد.
اختيار الإعداد المناسب
مصفوفة قرارات عملية:
- RPO = 0، الكتابات تتحمل زمن استجابة أعلى: استخدم النسخ المتزامن إلى تابع واحد على الأقل. AWS RDS Multi-AZ وGoogle Cloud SQL HA وPostgreSQL مع
synchronous_commit = onجميعها تُحقق هذا. - كتابة سريعة، يمكن تحمّل نافذة صغيرة من فقدان البيانات: نسخ غير متزامن مع تعافٍ تلقائي (Patroni، Orchestrator). اقبل أن التعافي قد يخسر ثواني قليلة من آخر الكتابات.
- قراءات عبر مناطق جغرافية بزمن استجابة منخفض: نسخ متطابقة للقراءة غير متزامنة في كل منطقة. اقبل أن قراءات التابع عبر المناطق قد تكون قديمة قليلاً.
- الحاجة إلى المتانة والسرعة معاً: نسخ شبه متزامن — تابع متزامن واحد في نفس مركز البيانات، والبقية غير متزامنين بما فيهم النسخ عبر المناطق.