كلاود
بنية تحتية

عنقود MariaDB Galera: ثلاث عقد ولا نقطة فشل واحدة

كلاود|١ نوفمبر ٢٠٢٦|6 دقائق قراءة|٢٥ مشاهدة
عنقود MariaDB Galera: ثلاث عقد ولا نقطة فشل واحدة

عنقود Galera ينسخ كل معاملة إلى ثلاث عقد MariaDB بشكل متزامن، فلا تضيع بيانات ولا يتوقف النظام عند سقوط عقدة، مقابل مللي ثانية إضافية لكل كتابة وانضباط في تصميم التطبيق.

الجواب المختصر

MariaDB Galera Cluster يربط ثلاث عقد MariaDB أو أكثر بنسخ متزامن متعدد الكتابة: كل معاملة تُرسل لكل العقد قبل أن يكتمل COMMIT، وكل عقدة تتحقق من عدم تعارضها (certification) ثم تطبقها. النتيجة أن البيانات في العقد الثلاث متطابقة في كل لحظة، فإن سقطت عقدة يستمر النظام على الاثنتين الباقيتين دون أن تضيع معاملة مؤكدة واحدة ودون تحويل يدوي.

لماذا ثلاث لا اثنتان؟ لأن Galera يعمل بالنصاب (quorum): المجموعة التي تملك أكثر من نصف الأصوات هي وحدها التي تقبل الكتابة. مع عقدتين، سقوط واحدة يترك 50% وهذا ليس أغلبية، فتتوقف العقدة الباقية عن خدمة الاستعلامات حمايةً للبيانات. مع ثلاث، سقوط واحدة يترك 66% فيستمر العمل.

الثمن زمن كتابة أعلى بمقدار رحلة شبكة واحدة على الأقل لكل COMMIT، وهو من 1 إلى 2 مللي ثانية بين عقد في نفس المركز، إضافة إلى انضباط في التطبيق: جداول InnoDB فقط، مفتاح أساسي لكل جدول، وإعادة محاولة المعاملات التي ترفضها شهادة التعارض. يستحق العنقود ذلك حين تكون كلفة ساعة توقف لنظام ERP أعلى من كلفة سيرفرين إضافيين.

متى يستحق نظامك عنقوداً

البديل الأبسط هو خادم أساسي ونسخة غير متزامنة (async replica) مع تحويل يدوي أو شبه آلي. هذا يكفي لمعظم الأنظمة، لكنه يحمل خطرين: النسخة قد تتأخر ثوانٍ فتضيع آخر المعاملات عند السقوط، والتحويل نفسه يستغرق من دقيقة إلى 15 دقيقة حسب جاهزية الفريق. Galera يلغي الخطرين معاً.

العنقود مناسب لنظام ERP أو CRM يعمل عليه موظفون طوال اليوم، والقراءة فيه أكثر من الكتابة بنسبة 4 إلى 1 أو أعلى، ولا يتحمل فقدان فاتورة أو قيد محاسبي. في المقابل لا يناسب الأحمال التي تكتب بكثافة على نفس الصفوف، مثل عداد مخزون واحد يحدّثه مئة طلب في الثانية، لأن تعارضات الشهادة ستتكرر وتنهار الإنتاجية، كما لا يناسب قاعدة تتجاوز فيها معاملة واحدة مئات الآلاف من الصفوف، لأن كل معاملة تُنسخ كاملة دفعة واحدة.

عدد العقدالنصاب المطلوبالأعطال المحتملة دون توقف
220
321
431
532

لاحظ أن أربع عقد لا تعطيك أكثر من ثلاث، لذلك الأعداد الفردية هي القاعدة. إن كانت الميزانية لا تتحمل ثلاثة خوادم قواعد، يمكن أن تكون الثالثة garbd، وهو حَكَم Galera يشارك في التصويت فقط ولا يخزن بيانات، ويعمل على أي سيرفر تطبيق موجود.

كلفة الكتابة المتزامنة على زمن الاستجابة

عند COMMIT ترسل العقدة مجموعة الكتابة (write-set) لكل العقد عبر بث مرتب، وتنتظر حتى تُستلم في كل مكان، ثم تُقرّ محلياً. هذا يعني أن زمن الشبكة بين أبعد عقدتين يضاف لكل معاملة كتابة. في مركز واحد بالرياض الرقم من 1 إلى 2 مللي ثانية، فمعاملة كانت تأخذ 4ms تصبح 6ms تقريباً. القراءة لا تتأثر إطلاقاً لأنها محلية.

العامل الثاني هو flow control: إن تأخرت عقدة في تطبيق المعاملات وامتلأ طابورها، تطلب من الجميع التوقف حتى تلحق. أي أن العنقود يمشي بسرعة أبطأ عقدة فيه، لذلك يجب أن تكون العقد الثلاث بنفس الموارد. عقدة بقرص أبطأ أو ذاكرة أقل ستسحب الاثنتين معها.

العامل الثالث هو التعارض: إن عدلت معاملتان على عقدتين مختلفتين نفس الصف في نفس اللحظة، تفوز الأولى في الترتيب وتُرفض الثانية بخطأ deadlock رقم 1213 عند COMMIT لا قبله. التطبيق يجب أن يعيد المحاولة، وأغلب أطر العمل الحديثة تدعم ذلك، لكن يجب أن تتأكد.

إعداد wsrep الأساسي

على كل عقدة، في ملف إعداد MariaDB، القيم الجوهرية هي:

  • wsrep_on = ON وwsrep_provider يشير إلى مكتبة libgalera_smm.so.
  • wsrep_cluster_address = gcomm://10.0.0.11,10.0.0.12,10.0.0.13 بعناوين العقد الثلاث.
  • wsrep_cluster_name موحد، وwsrep_node_address عنوان العقدة نفسها.
  • wsrep_sst_method = mariabackup لنقل الحالة الكاملة دون قفل العقدة المانحة.
  • binlog_format = ROW وdefault_storage_engine = InnoDB وinnodb_autoinc_lock_mode = 2.

افتح بين العقد فقط المنافذ 3306 و4567 و4568 و4444، ولا شيء منها للإنترنت. أطلق العقدة الأولى بـgalera_new_cluster ثم ابدأ الخدمة عادياً على الثانية والثالثة، وستنضمان وتسحبان البيانات تلقائياً. تأكد بعدها أن wsrep_cluster_size يساوي 3.

قبل نقل نظام قائم، افحص الجداول: أي جدول MyISAM يجب تحويله إلى InnoDB، وأي جدول بلا مفتاح أساسي يجب أن تضيف له مفتاحاً، لأن Galera يعتمد على المفتاح لتحديد الصفوف عند التطبيق، والجدول بلا مفتاح يُبطئ العنقود كله.

ProxySQL أو HAProxy أمام العنقود

التطبيق لا يجب أن يعرف عناوين العقد الثلاث. ضع أمامها موزعاً يوجه الاتصالات للعقد السليمة فقط. HAProxy هو الخيار الأبسط: توزيع TCP مع فحص صحة يسأل كل عقدة إن كانت Synced، ويخرج من التوزيع أي عقدة ليست كذلك. أما ProxySQL فيفهم بروتوكول MySQL نفسه، فيستطيع فصل القراءة عن الكتابة، وتخزين نتائج الاستعلامات المتكررة، ومراقبة حالة wsrep مباشرة.

توصيتنا العملية مع أي منهما نمط "كاتب واحد": كل الكتابات تذهب لعقدة واحدة والقراءات تتوزع على الثلاث، فإن سقط الكاتب يرقّي الموزع عقدة أخرى خلال ثوانٍ. هذا النمط يلغي تعارضات الشهادة تقريباً ويحتفظ بكل مزايا التزامن. ضع ProxySQL على سيرفرات التطبيق نفسها بنسخة لكل سيرفر، فلا يصبح هو نقطة الفشل الوحيدة التي بنيت العنقود لتتجنبها.

سيناريوهات الانقسام وكيف تتعافى

عقدة واحدة انعزلت

العقدة المعزولة ترى نفسها ثلثاً، فتنتقل لحالة non-Primary وترفض الاستعلامات، بينما تستمر العقدتان الأخريان. عند عودة الشبكة تنضم تلقائياً وتسحب ما فاتها عبر IST، أي نقل تزايدي من ذاكرة gcache، بشرط أن تكون gcache كبيرة بما يكفي. اضبط gcache.size على 2GB أو أكثر حتى لا تُجبر على SST كامل.

انقطاع الكهرباء عن العقد الثلاث

بعد عودة الكل لن يبدأ العنقود وحده، لأن كل عقدة لا تعرف إن كانت الأحدث. افحص ملف grastate.dat في كل عقدة وابحث عن أعلى seqno، أو شغّل mariadbd بخيار wsrep-recover إن كانت القيمة -1. اضبط safe_to_bootstrap على 1 في العقدة الأحدث فقط وأطلقها بـgalera_new_cluster، ثم الباقي عادياً. الإطلاق من العقدة الخطأ يعني فقدان آخر المعاملات.

انقسام كامل 1-1-1

إن انقطعت الشبكة بين العقد الثلاث معاً، تصبح كل واحدة non-Primary ويتوقف العنقود عن الكتابة. هذا تصرف صحيح، فالبديل كان كتابات متضاربة لا يمكن دمجها. بعد التأكد من أي عقدة هي الأحدث، نفّذ عليها SET GLOBAL wsrep_provider_options='pc.bootstrap=YES' لتصبح Primary، وستنضم الباقيات إليها حين تعود الشبكة.

المراقبة اليومية

أربعة متغيرات تكفي لمعرفة صحة العنقود: wsrep_cluster_size يجب أن يكون 3، وwsrep_cluster_status يجب أن يكون Primary، وwsrep_local_state_comment يجب أن يكون Synced، وwsrep_flow_control_paused يجب أن يبقى تحت 0.1، فإن تجاوزها فعقدة ما تبطئ الجميع. اربط هذه بتنبيهات فورية، فعنقود يعمل بعقدتين دون أن يعلم أحد هو عنقود على بُعد عطل واحد من التوقف.

تقدير الكلفة السنوية لثلاثة خوادم

العقد يجب أن تكون متماثلة. لنظام ERP متوسط بقاعدة حتى 30GB، ثلاثة خوادم بباقة نمو (2 vCPU و4GB RAM و40GB SSD) بـ6,900 ريال لكل خادم سنوياً، أي 20,700 ريال سنوياً للعنقود كاملاً. للأحمال الأثقل، ثلاثة خوادم بباقة أعمال (4 vCPU و8GB RAM) بـ11,500 ريال لكل خادم، أي 34,500 ريال سنوياً، مع إضافة +100GB SSD بـ500 ريال لكل عقدة إن احتجت مساحة. الأسعار شاملة الضريبة.

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

القرار العملي

  • إن كانت ساعة التوقف تكلفك أكثر من سيرفرين إضافيين، فالعنقود مبرر.
  • افحص الجداول اليوم: InnoDB فقط ومفتاح أساسي لكل جدول.
  • ابدأ بنمط الكاتب الواحد خلف ProxySQL، ولا تفعّل الكتابة على العقد الثلاث إلا لحاجة مثبتة.
  • تدرب على سيناريو إطفاء العقد الثلاث وإعادة الإطلاق من الأحدث قبل أن تحتاجه في الإنتاج.
مشاركة