النسخ المتماثل لقواعد البيانات
النسخ المتماثل لقواعد البيانات
خادم قاعدة البيانات الواحد هو نقطة فشل وحيدة. إذا تعطّل هذا الجهاز، تتوقف خدمتك بالكامل. حتى قبل وقوع الأعطال، ثمة سقف صلب لعدد استعلامات القراءة التي يستطيع الخادم الواحد معالجتها — كل استعلام وتقرير تحليلي ومهمة خلفية تتنافس على نفس المعالج والذاكرة والإدخال/الإخراج. النسخ المتماثل (Replication) هو ممارسة الاحتفاظ بنسخ متزامنة من بياناتك على خوادم متعددة، مما يحل المشكلتين في آنٍ واحد: يُزيل نقطة الفشل الوحيدة ويوزع حِمل القراءة على أجهزة متعددة.
فهم النسخ المتماثل بعمق — ولا سيما المقايضات بين الأنماط المتزامنة وغير المتزامنة — أمر ضروري لكل مهندس يصمم أنظمة يجب أن تتمتع بالتوافر العالي والاتساق معًا.
نسخ القائد-التابع (Leader-Follower)
أكثر طوبولوجيات النسخ المتماثل شيوعًا هي القائد-التابع (تُعرف أيضًا بـ Primary-Replica أو Master-Slave). القواعد بسيطة:
- عقدة واحدة تُعيَّن قائدًا (Leader/Primary). تذهب جميع عمليات الكتابة إلى القائد — فهو المصدر الوحيد الموثوق للحقيقة.
- عقدة أو أكثر تكون تابعة (Followers/Replicas). تتلقى نسخة من كل عملية كتابة من القائد وتطبّقها على تخزينها الخاص. يستقبل التابعون استعلامات القراءة.
- يوجّه العملاء عمليات الكتابة إلى القائد وعمليات القراءة إلى أي تابع (أو القائد، حسب احتياجات الاتساق).
يُستخدم هذا النموذج في النسخ المتدفق لـ PostgreSQL، ونسخ السجل الثنائي لـ MySQL، ومجموعات replica في MongoDB (في وضع primary-secondary)، ومعظم قواعد البيانات المُدارة (قواعد بيانات AWS RDS read replicas، وGoogle Cloud SQL، وغيرها).
كيف يعمل النسخ المتماثل داخليًا
عند إتمام عملية كتابة على القائد، تسجّلها قاعدة البيانات في سجل النسخ المتماثل (يُسمى Write-Ahead Log في PostgreSQL، أو السجل الثنائي في MySQL). يبث القائد إدخالات السجل إلى كل تابع. يطبق كل تابع هذه الإدخالات بالترتيب، ليمتلك في النهاية نسخة متطابقة من البيانات.
السؤال الجوهري الذي يجب أن تجيب عنه كل منظومة نسخ متماثل هو: متى يعتبر القائد عملية الكتابة "مكتملة"؟ ومن هنا ينشأ الوضعان الأساسيان.
النسخ المتماثل المتزامن (Synchronous)
في الوضع المتزامن، ينتظر القائد تأكيدًا من تابع واحد على الأقل قبل تأكيد الكتابة للعميل. لا تعتبر عملية الكتابة مكتملة حتى يخزّن التابع البيانات بشكل دائم.
الضمان: إذا تعطّل القائد فور تأكيد الكتابة، فإن تابعًا واحدًا على الأقل يمتلك تلك البيانات. لا تُفقد أي كتابة مُؤكَّدة أبدًا.
التكلفة: يجب أن تُكمل كل عملية كتابة رحلة شبكية ذهابًا وإيابًا إلى التابع قبل أن يحصل العميل على استجابة. إذا كان القائد والتابع في نفس مركز البيانات، يُضاف 1-5 ميلي ثانية. عبر المناطق، يُضاف 50-200 ميلي ثانية — وهذا التأخير على المسار الحرج لكل عملية كتابة.
النسخ المتماثل غير المتزامن (Asynchronous)
في الوضع غير المتزامن، يؤكد القائد الكتابة للعميل فور كتابتها على قرصه المحلي. يشحن التغيير إلى التوابع في الخلفية — لا ينتظر العميل أبدًا تأكيدات التوابع.
الفائدة: تأخير الكتابة منخفض كما في قاعدة بيانات مفردة. أعطال التوابع لا تعيق القائد أبدًا. هذا الوضع هو الافتراضي في نسخ MySQL وقواعد بيانات AWS RDS read replicas.
التكلفة: إذا تعطّل القائد بعد تأكيد الكتابة للعميل لكن قبل إرسالها للتوابع، تُفقد تلك الكتابة. يُسمى هذا تأخر النسخ المتماثل (Replication Lag)، ويُفضي إلى مخاطرة باتساق البيانات: قد يكتب العميل بيانات إلى القائد ثم يقرأ من تابع لم يطبّق تلك الكتابة بعد، فيرى بيانات قديمة.
pg_stat_replication.write_lag في PostgreSQL أو Seconds_Behind_Source في MySQL) وأصدر تنبيهات عند تجاوز حد التحمل.
مقارنة جنبًا إلى جنب: المتزامن مقابل غير المتزامن
الفشل والترقية (Failover and Promotion)
عند فشل القائد، يجب ترقية أحد التوابع ليصبح القائد الجديد. تُسمى هذه العملية الاستبدال عند الفشل (Failover). تعتمد سلاسة هذه العملية على وضع النسخ المتماثل:
- مع النسخ المتزامن: التابع المُرقَّى مضمون أن يمتلك كل عملية كتابة مُؤكَّدة. الاستبدال نظيف وفقدان البيانات صفر.
- مع النسخ غير المتزامن: قد يكون التابع متأخرًا قليلًا. تُفقد أي كتابات أكدها القائد للعملاء لكن لم يرسلها للتوابع بعد. تقبل معظم قواعد البيانات المُدارة (RDS وCloud SQL) هذه المقايضة لأن نافذة فقدان الكتابة في الظروف العادية تكون أقل من ثانية.
بعد الترقية، يجب إعادة تهيئة التوابع القديمة لتتبع القائد الجديد. في أنظمة مثل PostgreSQL Patroni أو MySQL Orchestrator، تكون هذه الإعادة تلقائية.
توسيع القراءة واتساق "اقرأ ما كتبته"
من الفوائد الرئيسية للتوابع هو توسيع القراءة (Read Scaling): يمكنك إضافة توابع لاستيعاب حركة قراءة أكبر دون المساس بالقائد. قائد واحد مع خمسة توابع يستطيع خدمة 5 أضعاف استعلامات القراءة مقارنةً بخادم منفرد، بينما تبقى الكتابات على القائد.
ومع ذلك، يُقدّم هذا مشكلة اتساق خفية. افترض أن مستخدمًا حدّث صورة ملفه الشخصي. ذهبت الكتابة إلى القائد. بعد ميلي ثانية أعاد المستخدم تحميل الصفحة — لكن توجّهت القراءة إلى تابع لم يطبّق الكتابة بعد. يرى المستخدم صورته القديمة. يُسمى هذا الانتهاك القراءة القديمة (Stale Read) أو انتهاك اتساق "اقرأ ما كتبته".
الحلول الشائعة:
- إعادة توجيه القراءات التي كتبها المستخدم الحالي (خلال N ثانية) إلى القائد.
- تتبع موضع النسخ المتماثل الذي كتبه العميل آخر مرة؛ توجيه القراءات فقط إلى التوابع التي لحقت بذلك الموضع.
- قبول نافذة تناسق صغيرة للبيانات التي لم يعدّلها المستخدم مباشرةً (مثل تغذية اجتماعية — رؤية منشور متأخرًا بثانية أمر مقبول).
النسخ المتماثل شبه المتزامن
يقدم MySQL حلًا وسطًا يُسمى النسخ المتماثل شبه المتزامن (Semi-Synchronous Replication): ينتظر القائد تأكيدًا من تابع واحد على الأقل بأنه استلم الكتابة (لكن ليس بالضرورة أن يكون قد حفظها على القرص). يُزيل هذا فقدان البيانات عند عطل القائد بتكلفة تأخير أقل من النسخ المتزامن الكامل، مع ضمان مغادرة البيانات لجهاز القائد.
ملخص
النسخ المتماثل للقائد-التابع هو النمط الأساسي لتحقيق التوافر العالي وتوسيع القراءة في قواعد البيانات. القائد هو سلطة الكتابة الوحيدة؛ التوابع تبث سجل النسخ المتماثل وتخدم القراءات. المقايضة الجوهرية بين الوضع المتزامن — الذي يضمن عدم فقدان أي كتابة مُؤكَّدة عند الاستبدال لكن يُضيف تأخيرًا شبكيًا لكل كتابة — والوضع غير المتزامن — الذي يوفر كتابة بتأخير منخفض على حساب نافذة محتملة لفقدان البيانات والاتساق التدريجي في القراءة. في الممارسة العملية، تستخدم معظم الأنظمة واسعة النطاق النسخ غير المتزامن افتراضيًا وتُضيف تقنيات تعويضية (توجيه، تتبع موضع النسخ) لتحقيق اتساق مقبول لحالات الاستخدام المختلفة.