توسيع نطاق القراءة باستخدام النسخ المتماثلة
توسيع نطاق القراءة باستخدام النسخ المتماثلة
معظم تطبيقات الويب في بيئات الإنتاج تعتمد بشكل كثيف على عمليات القراءة. موقع تجارة إلكترونية نموذجي قد ينفذ 10 عمليات قراءة لصفحة منتج مقابل كل عملية كتابة واحدة لطلب. تغذية اجتماعية قد تخدم 100 عملية قراءة لجدول زمني مقابل كل منشور جديد واحد. حين يعجز عقدة قاعدة البيانات المنفردة عن مواكبة هذا الحجم من القراءة، تكون النسخ المتماثلة للقراءة خط الدفاع الأول — وغالباً الأكثر فعالية من حيث التكلفة.
اختناق العقدة المنفردة
لكل خادم قاعدة بيانات حدٌّ أقصى: أنوية المعالج، وذاكرة الوصول العشوائي لمجموعة المخزن المؤقت، وعرض نطاق إدخال/إخراج القرص، وإنتاجية الشبكة. حين تستنزف استعلامات القراءة هذه الموارد، يتباطأ كل استعلام — بما فيها عمليات الكتابة. يمكنك إضافة فهارس وضبط الاستعلامات وترقية الأجهزة، لكن في نهاية المطاف ستصل إلى سقف. الخطوة التالية هي توزيع عبء القراءة عبر عدة نسخ من قاعدة البيانات.
كيف تعمل النسخ المتماثلة
النسخ المتماثل لقاعدة البيانات هو عملية النسخ المستمر للبيانات من عقدة واحدة — العقدة الأساسية (تُعرف أيضاً بالقائد أو المصدر) — إلى عقدة أو أكثر تُسمى النسخ المتماثلة (تُعرف أيضاً بالتابعين أو الاحتياطيين). العقدة الأساسية تقبل عمليات القراءة والكتابة معاً. النسخ المتماثلة تقبل القراءة فقط.
آلية النسخ المتماثل تختلف حسب محرك قاعدة البيانات لكن المفهوم واحد في كل مكان:
- تصل عملية كتابة إلى العقدة الأساسية. تُسجّل العقدة الأساسية التغيير في تخزينها الخاص وتدوّنه في سجل النسخ المتماثل (يُسمى binlog في MySQL، وWAL — سجل الكتابة المسبق — في PostgreSQL).
- تحافظ كل نسخة متماثلة على اتصال بالعقدة الأساسية وتبث ذلك السجل باستمرار.
- تطبّق النسخة المتماثلة نفس العمليات على نسختها الخاصة من البيانات، وتبقى متزامنة.
- تُخدَّم عمليات القراءة الموجهة إلى نسخة متماثلة كلياً من تخزينها المحلي — العقدة الأساسية لا تُشارك فيها إطلاقاً.
النسخ المتماثل المتزامن مقابل غير المتزامن
مدى سرعة لحاق النسخة المتماثلة بالعقدة الأساسية يحكمه وضع النسخ المتماثل:
- غير المتزامن (الافتراضي في معظم الأنظمة): تُسجّل العقدة الأساسية عملية الكتابة وتُخطر العميل فوراً، دون انتظار أي نسخة متماثلة لتطبيق التغيير. النسخ المتماثلة تلحق في الخلفية — عادةً خلال ميلي ثانية على شبكة المنطقة المحلية، لكن ربما ثوانٍ أو دقائق تحت حِمل ثقيل أو شبكة بطيئة. هذا الخيار يمنح أعلى إنتاجية لكنه يُدخل تأخر النسخ المتماثل.
- المتزامن (semi-sync في MySQL، synchronous standby في PostgreSQL): تنتظر العقدة الأساسية تأكيد نسخة متماثلة واحدة على الأقل باستلام الكتابة قبل إخطار العميل. هذا يمنع فقدان البيانات عند فشل العقدة الأساسية لكنه يُضيف زمن استجابة للكتابة يعادل رحلة شبكة واحدة على الأقل.
- شبه المتزامن: حل وسط عملي — نسخة متماثلة واحدة يجب أن تُؤكد، والباقي غير متزامن. يُستخدم بكثرة في إعدادات MySQL عالية التوفر.
تطبيق فصل القراءة والكتابة
تُوفر معظم البنى التقنية الحديثة إحدى هذه الآليات على الأقل لفصل اتصالات القراءة والكتابة:
- التوجيه على مستوى التطبيق: إطار ORM أو مكتبة قاعدة البيانات لديك يدعم سلاسل اتصال متعددة. الكتابة تستخدم اتصال
write؛ القراءة تستخدم تجمع اتصالاتread. إعداد اتصالات القراءة/الكتابة في Laravel مثال نموذجي — تُدرج مضيفاً أو أكثر لـreadومضيفاً لـwrite؛ يوجّه الإطار تلقائياً. - التوجيه على مستوى الوكيل: وكيل وسيط مثل ProxySQL (MySQL) أو PgBouncer + pgpool-II (PostgreSQL) يجلس بين تطبيقك وقاعدة البيانات. يفحص عبارات SQL ويوجّه عبارات
SELECTإلى النسخ المتماثلة وINSERT/UPDATE/DELETE/BEGINإلى العقدة الأساسية. التطبيق يرى سلسلة اتصال واحدة فقط. - النسخ المتماثلة المُدارة سحابياً: Amazon RDS وGoogle Cloud SQL وAzure Database جميعها تُقدم نسخاً متماثلة للقراءة كميزة بنقرة واحدة. AWS Aurora تتجاوز ذلك بتوفير نقطة نهاية reader واحدة تُوازن التحميل عبر جميع النسخ المتماثلة تلقائياً.
كم عدد النسخ المتماثلة التي تحتاجها؟
ابدأ بالأرقام. لنفترض أن عقدتك الأساسية تتعامل مع 8,000 استعلام قراءة في الثانية (QPS) وتريد البقاء تحت 60% استخدام للمعالج كهامش أمان. عند 60% تكون عقدتك الأساسية مريحة عند 5,000 QPS تقريباً. إذا كانت كل نسخة متماثلة لها نفس سعة العتاد:
- إجمالي حمل القراءة: 8,000 QPS
- السعة لكل عقدة عند 60%: 5,000 QPS
- النسخ المتماثلة المطلوبة: ⌈8,000 / 5,000⌉ = نسختان متماثلتان، تاركتين العقدة الأساسية للكتابة فقط
عملياً، أضف نسخة متماثلة إضافية واحدة على الأقل كاحتياطي حار ولاستيعاب ارتفاعات حركة المرور. المنصات الكبيرة مثل GitHub وShopify تشغّل عشرات النسخ المتماثلة لكل شريحة — ليس فقط لإنتاجية القراءة، بل أيضاً للقرب الجغرافي (وضع نسخة متماثلة في أوروبا لخدمة المستخدمين الأوروبيين بزمن استجابة أقل) ولأعباء التحليل (تشغيل تقارير GROUP BY الثقيلة على نسخة متماثلة حتى لا تُؤثر أبداً على العقدة الأساسية).
تأخر النسخ المتماثل: القياس والإدارة
تأخر النسخ المتماثل هو الزمن الفاصل بين تسجيل الكتابة على العقدة الأساسية وظهورها على النسخة المتماثلة. يمكنك مراقبته مباشرة:
استراتيجيات للحفاظ على التأخر منخفضاً:
- النسخ المتماثل المتوازي: MySQL 8.0+ وPostgreSQL 10+ يستطيعان تطبيق سجل النسخ المتماثل باستخدام خيوط متعددة بالتوازي، مما يُقلل التأخر بشكل كبير تحت معدلات الكتابة العالية.
- تحجيم النسخ المتماثلة: امنح النسخ المتماثلة نفس مقدار الذاكرة العشوائية (أو أكثر) للعقدة الأساسية حتى تكون ذاكرة التخزين المؤقت دافئة بالتساوي.
- تجنب استعلامات التحليل الثقيلة على النسخ المتماثلة تحت التأخر الكبير — استعلام
SELECTطويل الأمد يمكنه الإمساك بأقفال تُعيق النسخ المتماثل. - راقب التأخر كمقياس SLO — أنذر عند تجاوز 5 ثوانٍ، وأرسل تنبيهاً عند تجاوز 30 ثانية.
تبديل الأدوار: عندما تفشل العقدة الأساسية
النسخة المتماثلة ليست مجرد أداة لتوسيع نطاق القراءة — إنها مسار الاسترداد عند فشل العقدة الأساسية. في إعداد عالي التوفر، تُعيَّن إحدى النسخ المتماثلة كـاحتياطي حار. عند توقف العقدة الأساسية، تُرقّي عملية تبديل أدوار آلية الاحتياطي إلى عقدة أساسية في غضون ثوانٍ، وتُحدّث جدول توجيه DNS أو الوكيل، وتُعيد النسخ المتماثلة الأخرى الاتصال بالعقدة الأساسية الجديدة.
الأدوات التي تُؤتمت هذا: Orchestrator (MySQL)، Patroni (PostgreSQL)، Amazon RDS Multi-AZ (مُدار بالكامل، تبديل أدوار تلقائي في ~60 ثانية). النسخ المتماثلة المُدارة سحابياً مع تبديل أدوار تلقائي أصبحت الآن المعيار لأي نظام إنتاجي لا يتحمل توقفاً لدقائق متعددة.
DROP TABLE أو صف بيانات تالف كُتب على العقدة الأساسية. احتفظ دائماً بنسخة احتياطية دورية منفصلة (مثل mysqldump، pg_dump، أو نسخة احتياطية قائمة على اللقطات) بالإضافة إلى نسخك المتماثلة.
المقايضات في لمحة
- فائدة — إنتاجية القراءة: توسع أفقي خطي لعمليات القراءة. أضف نسخة متماثلة، أضف 5,000–15,000 QPS من سعة القراءة.
- فائدة — التوزيع الجغرافي: نسخة متماثلة في كل منطقة تخدم المستخدمين المحليين بزمن استجابة لقاعدة البيانات أقل من 10 ميلي ثانية بدلاً من رحلات عبر المحيط.
- فائدة — التوفر العالي: النسخ المتماثلة تُضاعف كاحتياطيات، محوّلةً أعطال الأجهزة إلى ثوانٍ من التوقف بدلاً من ساعات.
- تكلفة — قابلية توسع الكتابة: النسخ المتماثل لا يُساعد الكتابات. كل كتابة لا تزال تذهب إلى عقدة أساسية واحدة. لأعباء الكتابة الكثيفة تحتاج إلى التجزئة (الدرس 8).
- تكلفة — الاتساق: النسخ المتماثل غير المتزامن يعني أن النسخ المتماثلة قد تتأخر. يجب تصميم التطبيقات لتتحمل الاتساق النهائي في مسارات القراءة، أو توجيه القراءات الحساسة إلى العقدة الأساسية.
- تكلفة — تعقيد التشغيل: المزيد من العقد يعني مزيداً من المراقبة ومنطق تبديل الأدوار وإدارة الاتصالات. استخدم وكيلاً أو خدمة مُدارة لاستيعاب هذا التعقيد.
SHOW STATUS LIKE 'Threads_running' أو ما يعادله.