التعافي من الكوارث وتعدد المناطق

نسخ البيانات عبر المناطق الجغرافية

18 دقيقة الدرس 4 من 27

نسخ البيانات عبر المناطق الجغرافية

نقل طبقة الحوسبة عبر المناطق أثناء تحويل الفشل أمرٌ سهل نسبياً — تُعيد توجيه DNS، وتُشغّل الخوادم، وتتركُ منسّقَ الحاويات يُعيد جدولة الـ Pods. أما نقل البيانات فهو مشكلة أصعب جوهرياً. للبيانات ثقلٌ خاص: يجب أن تكون متسقة وصامدة ومتاحة في المكان المناسب في الوقت المناسب. الخيارات التي تتخذها في بنية النسخ تحدد RPO الفعلي وتضع حداً أدنى صارماً لـ RTO. إذا أخطأت في هذه الخيارات، فإن خطة DR موجودة على الورق فقط.

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

يبدأ كل تصميم للنسخ عبر المناطق بقرار واحد: هل تنتظر الخادم الأساسي تأكيد النسخة الثانوية في المنطقة البعيدة للكتابة قبل إخطار العميل بنجاحها؟

النسخ المتزامن يعني أن الكتابة لا تُؤكَّد إلا بعد أن تثبّت نسخة واحدة على الأقل في المنطقة الثانوية. RPO يكون صفراً فعلياً — لا يمكن أن تضيع أي معاملة مُرتكَزة. التكلفة هي الكمون: إذا كان الخادم الأساسي في us-east-1 والنسخة في eu-west-1، فالرحلة ذهاباً وإياباً تستغرق نحو 80 ms. كل كتابة تُضيف هذه المدة. في أعباء العمل OLTP عالية الأداء، نادراً ما يكون النسخ المتزامن عبر المناطق ممكناً عملياً لمسافات تزيد على بضع مئات من الكيلومترات.

النسخ غير المتزامن يعني أن الخادم الأساسي يُقرّ الكتابة فوراً ويُرسل سجل التغييرات إلى النسخة في الخلفية. كمون الكتابة لا يتغير. المقايضة هي التأخر في النسخ: إذا انهار الخادم الأساسي قبل أن تُطبّق النسخة آخر ثوانٍ من السجل، ضاعت تلك المعاملات. في AWS مع RDS MySQL، يتراوح التأخر المعتاد عبر المناطق بين 50 ms وبضع ثوانٍ في الأحوال العادية، ويمكن أن يرتفع إلى دقائق أثناء طوفان كتابة أو ترحيل DDL ضخم.

مفتاح الفهم: لا يوجد وضع صحيح في كل الحالات. النسخ المتزامن مناسب للقيود المالية وتأكيدات الدفع وكل ما لا يُقبل فيه فقدان البيانات مع تحمّل كمون الكتابة. أما غير المتزامن فهو مناسب لحالة الجلسة وأحداث التحليلات وكتالوج المنتجات وكل ما يُقبل فيه فقدان بضع ثوانٍ مع الحاجة لإنتاجية كتابة عالية.

تأخر النسخ — فخٌّ في الإنتاج

كثيراً ما تُهيّئ الفِرق النسخَ غير المتزامن، وتقيس التأخر بـ 50 ms في مرحلة الاختبار، وتُعلن أن RPO لديها "شبه صفر". هذا أمر خطير. تأخر النسخ ليس ثابتاً — بل هو دالة لمعدل الكتابة وظروف الشبكة وقدرة النسخة على الإدخال/الإخراج. أثناء استيراد دُفعة ضخمة أو ترحيل مخطط أو ارتفاع حركة المرور، يرتفع التأخر بانتظام إلى دقائق. إذا انهار الخادم الأساسي في تلك اللحظة، تخسر دقائق من البيانات لا ملّي ثانية. راقب دائماً Seconds_Behind_Source (MySQL) أو pg_stat_replication.write_lag (PostgreSQL) كمقياس SLO مع حدود تنبيه.

فخ الإنتاج: لا تقرأ RPO من التأخر في الحالة المستقرة. بل قِس أقصى تأخر للنسخ على مدار 30 يوماً، وخاصةً خلال نوافذ النشر والمهام الدُّفعية. هذا الحد الأقصى هو RPO الواقعي في أسوأ الحالات. كثير من الفِرق تكتشف أن قاعدة البيانات ذات "5 ثوانٍ RPO" تصل انتظامياً إلى 4 دقائق من التأخر أثناء التصدير الأسبوعي للتحليلات.

النسخ عبر المناطق: خيارات محددة لكل قاعدة بيانات

في بيئات الحجم الكبير، تختار الفِرق آلية النسخ بناءً على محرك قاعدة البيانات وأهداف RPO/RTO وتحملها للتعقيد التشغيلي.

قاعدة بيانات Amazon Aurora العالمية

تستخدم Aurora Global Database طبقة نسخ مخصصة تتجاوز شحن سجل الإعادة الخاص بقاعدة البيانات. تُكتب التغييرات في طبقة التخزين الموزعة لـ Aurora وتُنسخ إلى ما يصل إلى خمس مناطق ثانوية باستخدام بروتوكول نسخ سريع. يكون تأخر النسخ عادةً أقل من ثانية، وكثيراً ما يكون أقل من 100 ms. أثناء تحويل الفشل، تُرقَّى المنطقة الثانوية بـ RPO أقل من ثانية و RTO قرابة دقيقة واحدة.

-- ترقية منطقة ثانوية في Aurora Global Database (AWS CLI) aws rds failover-global-cluster \ --global-cluster-identifier my-global-cluster \ --target-db-cluster-identifier arn:aws:rds:eu-west-1:123456789012:cluster:my-replica \ --allow-data-loss -- احذف هذا المفتاح للتبديل المخطط بدون فقدان بيانات -- التحقق من تأخر النسخ في كل منطقة ثانوية SELECT aws_region, status, replica_lag_in_msec FROM information_schema.replica_host_status ORDER BY replica_lag_in_msec DESC;

النسخ المنطقي في PostgreSQL عبر المناطق

بالنسبة لـ PostgreSQL المُدار ذاتياً على EC2 أو الأجهزة المادية، يتيح النسخ المنطقي (متاح منذ PG 10) نسخ جداول فردية أو مجموعات منها إلى مشترك بعيد. على عكس النسخ الفيزيائي (streaming)، يتحمّل النسخ المنطقي اختلاف الإصدارات الكبرى ويسمح للمشترك بأن يكون قابلاً للكتابة في الجداول غير المشتركة — وهي خاصية محورية في أنماط active-active. المقايضة هي أن النسخ المنطقي لا ينسخ DDL؛ يجب تطبيق تغييرات المخطط يدوياً على المشتركين قبل تطبيقها على الناشر، وإلا تنكسر فتحة النسخ.

-- على الخادم الأساسي (الناشر) في us-east-1 ALTER SYSTEM SET wal_level = logical; SELECT pg_reload_conf(); CREATE PUBLICATION orders_pub FOR TABLE orders, order_items, payments; -- على النسخة (المشترك) في eu-west-1 — يجب أن تكون الجداول موجودة بالمخطط ذاته CREATE SUBSCRIPTION orders_sub CONNECTION 'host=primary.us-east-1.internal port=5432 dbname=app user=replicator password=SECRET sslmode=require' PUBLICATION orders_pub; -- مراقبة التأخر على الناشر SELECT slot_name, confirmed_flush_lsn, pg_wal_lsn_diff(pg_current_wal_lsn(), confirmed_flush_lsn) AS lag_bytes FROM pg_replication_slots WHERE slot_type = 'logical';

نسخ Kafka عبر المناطق (MirrorMaker 2)

لبيانات تدفق الأحداث — العمود الفقري لخطوط البيانات الحديثة — ينسخ Kafka MirrorMaker 2 الموضوعات عبر التجمعات في مناطق مختلفة مع ترجمة إزاحات المستهلكين. الموضوعات في التجمع الثانوي تُسبق باسم مستعار لتجمع المصدر (us-east.orders)، ما يعني أن المستهلكين عند تحويل الفشل لا يحتاجون إلا إعادة توجيه خوادم bootstrap وتعديل أسماء الموضوعات. MM2 مبني على Kafka Connect ويرث نموذجه التشغيلي.

# إعداد موصّل MirrorMaker 2 — نسخ جميع الموضوعات المطابقة للنمط # يُنشر كموصّل Kafka Connect على تجمع DR في eu-west-1 { "name": "us-east-to-eu-west-mirror", "config": { "connector.class": "org.apache.kafka.connect.mirror.MirrorSourceConnector", "source.cluster.alias": "us-east", "source.cluster.bootstrap.servers": "kafka-us-east.internal:9092", "target.cluster.bootstrap.servers": "kafka-eu-west.internal:9092", "topics": "orders,payments,user-events", "replication.factor": "3", "sync.topic.configs.enabled": "true", "sync.topic.acls.enabled": "true", "emit.heartbeats.enabled": "true", "refresh.topics.interval.seconds": "30" } } # التحقق من تأخر إزاحة مجموعة المستهلكين (نُفَّذ على تجمع DR) kafka-consumer-groups.sh \ --bootstrap-server kafka-eu-west.internal:9092 \ --describe \ --group us-east.orders-service

معالجة التعارضات في النسخ النشط-النشط

عندما تقبل كلتا المنطقتين الكتابة — نمط active-active — يمكن تعديل السجل المنطقي ذاته في وقت واحد من منطقتين. هذه مشكلة أساسية في الأنظمة الموزعة لا حل مثالياً لها. الخيارات العملية هي:

  • آخر كتابة تفوز (LWW) بالساعة الحائطية: الكتابة ذات الطابع الزمني الأعلى تفوز. بسيطة لكنها خطرة — انحراف الساعات بين المناطق يعني أن كتابة من 200 ms مضت قد تُلغي صامتاً كتابة أحدث من المنطقة الأخرى.
  • LWW بساعة منطقية (CRDT أو ناقل إصدار): استبدال الساعة الحائطية بطابع زمني Lamport أو ناقل إصدار. تستخدم CockroachDB وDynamoDB متغيرات من هذا النهج. أصح لكن لا يزال يفقد كتابة واحدة صامتاً.
  • اكتشاف التعارض على مستوى التطبيق: وسم كل كتابة بمنطقة المنشأ ورقم تسلسلي. عند الدمج، اكتشف التعارضات صراحةً وادفعها لقائمة حل على مستوى التطبيق. يحافظ هذا على كلتا الكتابتين ويترك للمنطق التجاري القرار (مثلاً، جمع دلتا المخزون بدلاً من اختيار فائز).
  • تجنب التعارضات بالتصميم (ملكية الكيان): تقسيم الكيانات بحيث تمتلك كل منطقة مجموعة منفصلة. المنطقة A تمتلك معرّفات المستخدمين الزوجية، المنطقة B تمتلك الفردية. لا يُكتب أي كيان من منطقتين في آنٍ واحد. هذا النهج الأكثر موثوقية تشغيلياً وهو ما تصل إليه معظم الأنظمة واسعة النطاق.
ممارسة الشركات الكبرى: تعتمد معظم المنصات الناضجة على تقسيم ملكية الكيانات لمخازن بياناتها الحرجة، وتقبل active-passive لنسبة 5–10% من الكيانات التي لا يمكن تقسيمها. المتعدد-رئيسي الحقيقي مع حل التعارضات محجوز للبيانات الوصفية والإعدادات — وليس للبيانات التعاملية.

مخطط بنية النسخ عبر المناطق

Cross-Region Replication Topology Primary Region (us-east-1) Application Writes & Reads Primary DB Aurora / PG Kafka Cluster Event Stream Produce Replication Lag: Seconds_Behind_Source Monitor → alert on p99 spike WAL / Redo log shipped async DR Region (eu-west-1) Replica DB Read-only Kafka Mirror MirrorMaker 2 Standby App Inactive until failover On Failover: Promote Replica RPO = max observed lag Async Repl MM2 Mirror Promote
نسخ قاعدة البيانات غير المتزامن ونسخ Kafka من منطقة أساسية إلى منطقة DR. عند تحويل الفشل، تُرقَّى النسخة وتصبح التطبيقات الاحتياطية نشطة.

مراقبة صحة النسخ كـ SLO

تأخر النسخ ليس مقياساً تشغيلياً في الخلفية — بل هو SLO من الدرجة الأولى لأنه RPO الفوري لديك. قِس عليه وفقاً لذلك. في بيئات Amazon، تُنبّه الفِرق عند حدّين: تحذير عند 10 أضعاف متوسط التأخر، وتنبيه حرج عند اختراق حد SLO (مثلاً 60 ثانية لنظام يستهدف RPO دقيقة واحدة).

بالنسبة لـ Aurora Global Database، المقياس الرئيسي في CloudWatch هو AuroraGlobalDBReplicationLag. لـ PostgreSQL المُدار ذاتياً، اعرض pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) كـ Prometheus gauge عبر postgres_exporter. لـ Kafka MM2، مقياس kafka.connect:type=MirrorSourceConnector,attribute=replication-latency-ms يعطي تأخر شامل من طرف لطرف لكل موضوع.

الممارسة التشغيلية: اختبر مسار ترقية تحويل الفشل كل ربع سنة تحت ظروف تأخر حقيقية. أوقف الخادم الأساسي، قِس التأخر وقت الفشل، أكّد أن ترقية النسخة تنتج تحديداً بهذا القدر من البيانات المفقودة لا أكثر، وأكّد أن التطبيق الاحتياطي يُعيد الاتصال بنظافة. إذا لم تختبر مسار الترقية قط في ظروف تأخر واقعية، فإن RPO لديك نظري فقط.