عمليات النسخ المتماثل والعقد في OmniHSS
تخزن OmniHSS بيانات المشتركين، والمصادقة (AuC)، وبيانات IMS في قاعدة بيانات PostgreSQL محلية على كل عقدة. تضمن النسخ المتماثل المنطقي ثنائي الاتجاه لـ PostgreSQL مزامنة عدة عقد من OmniHSS. يشكل هذا شبكة نشطة-نشطة: كل عقدة هي رئيسية كاملة للقراءة/الكتابة، وأي كتابة على أي عقدة تنتشر إلى جميع العقد الأخرى. لا يوجد رئيس/احتياطي. يمكن لأي عقدة خدمة حركة مرور S6a و Cx/Dx وقبول التProvisioning في أي وقت.
تتناول هذه الوثيقة نموذج النسخ المتماثل. تشرح كيفية إضافة عقدة جديدة من OmniHSS وتحميلها بالبيانات. كما تشرح كيفية التحقق من الصحة، وإصلاح، وإزالة الأقران.
جدول المح��ويات
- نظرة عامة على الهيكلية
- كيفية اكتشاف الأقران
- التكوين
- إضافة عقدة جديدة من OmniHSS
- تحميل عقدة جديدة بالبيانات
- التحقق من النسخ المتماثل
- سلامة البيانات
- إزالة نظير
- النسخ الاحتياطي والاستعادة
- المقاييس
- استكشاف الأخطاء وإصلاحها
نظرة عامة على الهيكلية
تشغل كل عقدة من OmniHSS نسختها الخاصة من PostgreSQL. كل عقدة تنشر جميع جداول التطبيق الخاصة بها و تشترك في نشر كل نظير. origin = none يمنع حلقات النسخ المتماثل. على جداول الحالة سريعة التغيير، تحل الشبكة تعارضات الكتابة آخر كتابة تفوز (LWW) من خلال مقارنة updated_at.
كل رابط أعلاه هو اشتراك أحادي الاتجاه (واحد لكل اتجاه). بالنسبة لشبكة من N عقد، تحتفظ كل عقدة بـ N-1 اشتراكات. يستهلك الأقران N-1 من فتحات النسخ المتماثل للنشر الخاص بهم.
ما الذي يتم نسخه متماثلًا
| فئة الجدول | أمثلة | معالجة التعارض |
|---|---|---|
| بيانات رئيسية / موفرة | subscriber, key_set (AuC), sim, msisdn | لا حاجة: موفرة من مكان واحد في كل مرة |
| الحالة الديناميكية | subscriber_state, pdn_session, lte_call, ims_subscription | آخر كتابة تفوز على updated_at |
| محاسبة الهجرة | schema_migrations | مستبعدة من النسخ المتماثل |
يغطي النشر كل جدول في مخطط public باستثناء schema_migrations (كل عقدة تقوم بتشغيل هجراتها بشكل مستقل). عندما تقوم عقدتان بتحديث نفس صف الحا��ة بشكل متزامن، تحتفظ مشغلات LWW بأحدث updated_at بدلاً من أي تحديث وصل آخر.
كيفية اكتشاف الأقران
عندما يتم تمكين النسخ المتماثل، يقوم دور OmniHSS ببناء قائمة الأقران الخاصة به تلقائيًا من مصدرين:
- المضيفون الآخرون في مجموعة جرد
hssالمحلية: عقد OmniHSS المعرفة في نفس ملف الجرد/المضيف (على سبيل المثال، زوج محليhss01/hss02). لا تحتاج هذه إلى أن تكون مدرجة فيconnected_omnihss؛ يكفي أن تكون عضواً في المجموعة. - قائمة
connected_omnihssفي ملف الأقران البعيد للموقع: عقد OmniHSS المعرفة في ملف مضيف مختلف (مواقع أخرى). يمكن اكتشاف الأقران عبر الملفات هنا فقط، لأن جرد واحد ليس لديه معرفة بمجموعةhssالخاصة بآخر.
يقوم الدور بتصفية الأقران من المجموعة المحلية إلى المضيفين الذين هم مشاركون في النسخ المتماثل لـ OmniHSS: أولئك الذين تكون قيمة omnihss.replication.enabled لديهم true. العقدة التي لا تكون علامتها true لا يتم التقاطها كنظير للنسخ المتماثل.
يستبعد الدور المضيف الحالي من قائمة الأقران الخاصة به تلقائيًا، بحيث يمكن مشاركة نفس كتلة connected_omnihss من قبل كل موقع دون محاولة عقدة النسخ المتماثل من نفسها.
تسمية الكائنات
تقوم كل عقدة بتسمية كائنات النسخ المتماثل الخاصة بها بحيث لا تتعارض شبكة بأي حجم:
| كائن | الاسم | تم إنشاؤه في | فريد لكل |
|---|---|---|---|
| نشر | <self>_pub | هذه العقدة | العقدة |
| اشتراك | sub_from_<source> | هذه العقدة (المشترك) | (المشترك) |
| فتحة النسخ المتماثل | <subscriber>_from_<source> | المصدر (الناشر) | (المشترك، المصدر) الزوج |
يجب أن يتضمن اسم الفتحة المشترك. اعتبر ما يحدث إذا كان يتضمن فقط المصدر (الافتراضي لـ PostgreSQL، حيث ترث الفتحة اسم الاشتراك). ستقوم عقدتان تشتركان في نفس المصدر بمحاولة إنشاء فتحة بنفس الاسم على ذلك المصدر. ستفشل الاشتراك الثاني بعد ذلك مع "فتحة النسخ المتماثل موجودة بالفعل". إن تضمين المشترك يمنح كل رابط فتحة فريدة عالميًا.
المصالحة وسلامة --limit
تقوم كل عملية تشغيل للدور بمصالحة كائنات النسخ المتماثل للعقدة مقابل مجموعة الأقران الصحيحة الحالية (مجموعة hss المحلية + connected_omnihss، ناقص الذات):
- يتم إسقاط المنشورات الأخرى غير
<self>_pub(تنظف المنشورات القديمة/المعاد تسميتها تلقائيًا). - يتم تعطيل الاشتراكات التي لم يعد نظيرها في المجموعة الصحيحة، ويتم فصلها عن فتحتها البعيدة، وإسقاطها.
- يتم إسقاط فتحات النسخ المتماثل غير النشطة التي لا تغذي نظيرًا صحيحًا حاليًا. لا يتم لمس الفتحات النشطة أبدًا.
��ذا يجعل connected_omnihss هو قائمة الشبكة السلطوية: تقوم العملية التالية بتقليم نظير تمت إزالته منها (ومن مجموعات hss ذات الصلة) من كل عقدة. تمنع خاصيتان أمانيتان من أن يكون هذا مدمرًا:
--limitآمن. يتم اشتقاق المجموعة الصحيحة منgroups['hss']وconnected_omnihss، والتي تعكس دائمًا عضوية الجرد الكاملة بغض النظر عن--limit. تشغيل--limit hss01يقوم بمصالحة فقطhss01. لكنhss01لا يزال يرىhss02/hss03كصحيح ويحتفظ باشتراكاتهم. لا يقوم--limitأبدًا بتقليم الأقران المستبعدة.- المجموعات الفارغة لا تقلم أبدًا. يتم تخطي خطوات التقليم تمامًا بدلاً من مسح جميع النسخ المتماثل إذا كانت مجموعة الأقران الصحيحة تحسب إلى فارغة (على سبيل المثال، جرد جزئي مع HSS واحد و
connected_omnihssغير محملة).
تحذير قائمة سلطوية: نظرًا لأن التقليم تلقائي، فإن التشغيل يقوم بتقليم نظير عبر ملف يكون جزءًا حقيقيًا من الشبكة ولكنه مفقود من
connected_omnihss. احتفظ دائمًا بـconnected_omnihssمكتملًا لكل نظير عبر ملف.
التكوين
تمكين النسخ المتماثل
يتم التحكم في النسخ المتماثل لكل نشر بواسطة علامة omnihss.replication.enabled. تكون false بشكل افتراضي. قم بتعيينها في جرد الموقع أو group_vars:
omnihss:
database_type: "postgres"
database_host: "localhost"
database_port: 5432
database_name: "omnihss"
database_username: "hss"
database_password: "password"
replication:
enabled: true
| المعلمة | النوع | مطلوب | الافتراضي | الوصف |
|---|---|---|---|---|
database_type | سلسلة | لا | postgres | واجهة قاعدة البيانات. ينطبق النسخ ا��متماثل فقط على postgres. |
database_host | سلسلة | لا | localhost | مضيف قاعدة البيانات. يتم تكوين النسخ المتماثل فقط عندما تكون قاعدة البيانات محلية (localhost). |
database_port | عدد صحيح | لا | 5432 | منفذ PostgreSQL، ويستخدم أيضًا كمنفذ افتراضي لاتصالات الأقران. |
database_name | سلسلة | لا | omnihss | اسم قاعدة البيانات. يجب أن يتطابق عبر جميع الأقران. |
database_username | سلسلة | نعم | hss | دور تسجيل الدخول. تم إنشاؤه مع خاصية REPLICATION حتى يتمكن من قيادة النسخ المتماثل المنطقي. |
database_password | سلسلة | نعم | password | كلمة المرور لدور تسجيل الدخول. يجب أن تتطابق عبر جميع الأقران (تستخدم في سلاسل اتصال الأقران). |
replication.enabled | منطقي | لا | false | مفتاح رئيسي. عندما تكون true، يتم تكوين PostgreSQL للنسخ المتماثل المنطقي ويتم إنشاء المنشورات/الاشتراكات. |
عندما تكون replication.enabled هي true، يقوم الدور بتطبيق إعدادات PostgreSQL التالية على النسخة المحلية:
| الإعداد | القيمة | الغرض |
|---|---|---|
wal_level | logical | مطلوب لنشر التغييرات المنطقية. |
max_wal_senders | 10 | عمليات إرسال WAL المتزامنة (واحدة لكل نظير مشترك). |
max_replication_slots | 10 | فتحات النسخ المتماثل المنطقية (واحدة لكل نظير مشترك). |
listen_addresses | * | السماح للأقران بالاتصال عبر الشبكة. |
max_slot_wal_keep_size | 10GB (يمكن تجاوزها عبر omnihss.replication.max_slot_wal_keep_size) | حد على WAL المحتفظ به لفتحة متأخرة/عالقة. بعد ذلك، يقوم PostgreSQL بإبطال الفتحة (wal_status = lost) ويحرر WAL الخاص بها، بحيث لا يمكن أن يملأ الاشتراك المعطل القرص ويوقف العقدة. الحجم إلى قرص العقدة. يتم تنبيه "HSS Replication Slot WAL Lost" عندما يتم تفعيله، بحيث يمكنك إعادة تهيئة النظير. |
يتم تحديث pg_hba.conf للسماح بعنوان IP لكل نظير (/32) لكل من اتصالات all �� replication.
إعلان الأقران عبر المواقع (connected_omnihss)
يتم إعلان عقد OmniHSS البعيدة في ملف الأقران البعيد المشار إليه بواسطة متغير remote_peers_file الخاص بكل موقع (عادةً prod_master_peers.yml):
connected_omnihss:
- name: site-hss01
host: 10.4.2.142
port: 5432
- name: site-hss02
host: 10.4.2.143
port: 5432
- name: dev-hss01
host: 10.4.10.142
port: 5432
| المعلمة | النوع | مطلوب | الافتراضي | الوصف |
|---|---|---|---|---|
name | سلسلة | نعم | - | inventory_hostname للنظير. هذا يسمي الاشتراك (sub_from_<name>) ويحل نشر النظير (<name>_pub)، لذا يجب أن يتطابق مع اسم المضيف الفعلي للنظير. |
host | سلسلة | نعم | - | عنوان IP للنظير، يمكن الوصول إليه من هذه العقدة عبر شبكة الإشارة. |
port | عدد صحيح | لا | 5432 | منفذ PostgreSQL للنظير. يعود إلى database_port. |
نظرًا لأن ملف الأقران البعيد يتم تحميله بواسطة كل موقع، يجب أن تحتوي القائمة الكاملة لـ connected_omnihss على كل عقد OmniHSS في الشبكة. تتخطى كل موقع تلقائيًا عقده المحلية الخاصة به (فهي مغطاة بالفعل بواسطة مجموعة hss المحلية) وتتخطى نفسها.
إضافة عقدة جديدة من OmniHSS
إضافة عقدة لها مرحلتان متميزتان: الانضمام إلى الشبكة (حتى تتدفق التغييرات في كلا الاتجاهين) و تحميل البيانات الموجودة على العقدة الجديدة. تهم المرحلة الثانية لأن العقدة الجديدة تبدأ بقاعدة بيانات فارغة. انظر تحميل عقدة جديدة بالبيانات.
الخطوة 1: توفير المضيف
قم بتوفير VM والشبكات الأساسية كما هو الحال في أي عقدة OmniCore (انظر نشر Proxmox). يجب أن تصل العقدة إلى منفذ PostgreSQL لكل نظير (5432 بشكل افتراضي) عبر شبكة الإشارة، ويجب أن تتمكن الأقران من الوصول إليها.
الخطوة 2: إضافة العقدة إلى الجرد
أضف المضيف الجديد إلى ملف مضيف الموقع تحت مجموعة hss::
hss:
hosts:
site-hss01:
ansible_host: 10.4.2.142
gateway: 10.4.2.1
host_vm_network: "v401-omni-signalling"
site-hss03: # عقدة جديدة
ansible_host: 10.4.2.144
gateway: 10.4.2.1
host_vm_network: "v401-omni-signalling"
ثم أضفه إلى connected_omnihss في ملف الأقران البعيد حتى تتعلم المواقع الأخرى عنه:
connected_omnihss:
- name: site-hss03
host: 10.4.2.144
port: 5432
# ... إدخالات موجودة ...
الخطوة 3: تشغيل دور OmniHSS
قم بتشغيل كتاب خدمة OmniHSS ضد المضيف الجديد. يقوم هذا بتثبيت PostgreSQL و OmniHSS، ويقوم بتشغيل الهجرات الخاصة بقاعدة البيانات (إنشاء مخطط فارغ)، ويقوم بتكوين النسخ المتماثل المنطقي، وإنشاء النشر بالإضافة إلى اشتراك لكل نظير:
ansible-playbook -i hosts/Customer_Name/host_files/Production.yml \
services/omnihss.yml --limit site-hss03
أعد تشغيل الدور على الأقران الحالية (أو دع التشغيل المجدول التالي يتعامل معها) حتى تفتح pg_hba.conf للعقدة الجديدة وتقوم بإنشاء اشتراكها مرة أخرى. الاشتراكات هي غير قابلة للتكرار: يكتشف الدور ويخطي الاشتراكات الموجودة، ويصدر ALTER SUBSCRIPTION ... REFRESH PUBLICATION حتى تلتقط أي جداول جديدة.
في هذه المرحلة، أصبحت العقدة الجديدة عضوًا في الشبكة وتستقبل جميع الكتابات المستقبلية. لكنها لا تحتوي بعد على قاعدة المشتركين الحالية. تابع لتحميل بياناتها.
تحميل عقدة جديدة بالبيانات
ينشئ الدور الاشتراكات الآلية مع copy_data = false. هذا صحيح لشبكة خضراء (تبدأ كل عقدة فارغة في نفس الوقت: لا يوجد شيء لنسخه، والنسخ سيسبب تعارضات في الصفوف المكررة). لكن هذا يعني أن العقدة التي تنضم إلى شبكة مكتملة بالفعل تبقى فارغة باستثناء التغييرات التي تحدث بعد انضمامها.
اختر المسار الذي يتناسب مع حالتك:
شبكة خضراء
إذا كنت تقوم بإعداد جميع عقد OmniHSS معًا دون بيانات موجودة مسبقًا، فلا تحتاج إلى التهيئة. قم بتمكين النسخ المتماثل، وقم بتشغيل الدور عبر جميع العقد، وقم بتوفير المشتركين بشكل طبيعي. كل كتابة تتكرر إلى جميع الأعضاء.
الخيار A: تهي��ة عبر النسخ والاستعادة (موصى به)
خذ لقطة من نظير صحي واستعدها على العقدة الجديدة. ثم دع النسخ المتماثل يحمل التغييرات المستمرة. يعيد هذا استخدام أدوات النسخ الاحتياطي/الاستعادة القياسية وهو النهج الأكثر قابلية للتنبؤ، بما في ذلك لمجموعات البيانات الكبيرة.
-
قم بعمل نسخة احتياطية من نظير صحي. ينتج عن هذا
pg_dumpلقاعدة بيانات OmniHSS (تم أخذه مع--no-publications --no-subscriptions، بحيث لا يتم نقل كائنات النسخ المتماثل) على جهاز التحكم:ansible-playbook -i hosts/Customer_Name/host_files/Production.yml \
services/backup.yml --limit site-hss01يتم حفظ النسخة الاحتياطية كـ
backups/<Site_Name>/hss_dump_<hostname>_<timestamp>.sql. -
استعادة على العقدة الجديدة. يتوقف كتاب الاستعادة عن OmniHSS، ويسقط ويعيد إنشاء قاعدة البيانات، ويستعيد النسخة الاحتياطية، ويعيد تشغيل الخدمة. يأخذ نسخة احتياطية قبل الاستعادة للهدف أولاً:
ansible-playbook -i hosts/Customer_Name/host_files/Production.yml \
util_playbooks/restore_hss.yml --limit site-hss03أضف
-e skip_pre_restore_backup=trueلتخطي تلك النسخة الاحتياطية قبل الاستعادة — مفيدة عندما يكون الهدف عقدة جديدة أو فارغة بالفعل، أو عندما تكون النسخة الاحتياطية بطيئة ومحتوياتها الحالية معروفة بأنها عديمة الفائدة. لا يتم حفظ أي شيء، لذلك لا يمكن استرداد البيانات الحالية للعقدة.عند المطالبة، قدم المسار إلى النسخة الاحتياطية SQL من الخطوة 1 واترك مسار التكوين فارغًا (لأن العقدة الجديدة لديها تكوينها الخاص من تشغيل الدور).
-
تأكيد تدفق النسخ المتماثل. الآن تطبق الاشتراكات الحالية للعقدة الجديدة (
copy_data = false) التغييرات فوق اللقطة المستعادة. قم بتشغيل التحقق أدناه.
نافذة الصيانة: هناك نافذة صغيرة بين النسخة الاحتياطية واللحظة التي تلحق فيها النسخ المتماثل. خلال ذلك، لم تعد تغييرات التProvisioning على الأقران موجودة بعد على العقدة الجديدة. تتغير بيانات المشترك الرئيسية بشكل نادر، وتتعافى الحالة الديناميكية (
subscriber_state,pdn_session,lte_call,ims_subscription) من حركة المرور الحية، لذا فإن نافذة النشاط المنخفضة كافية. لا تقم بتوفير مشتركين جدد خلال التهيئة.
الخيار B: تهيئة باستخدام كتاب التهيئة (موصى به)
يهيئ كتاب seed_hss_replication.yml من نظير مختار واحد دون عيوب النسخ الضخم الخام. يعيد إنشاء الاشتراك كاشتراك فقط للبث (copy_data = false، بدون جداول متزامنة). ثم يقوم بملء الصفوف الموجودة في جدول الرئيس بتحميل آمن من حيث التعارض. subscriber_state هو جزء من الملء: إنه بيانات هيكلية 1:1 (كل مشترك يشير إلى واحد بواسطة FK، تم إنشاؤه مرة واحدة عند التProvisioning). تخطيه يترك كل مشترك تم ملؤه يتيمًا، مما يكسر API و S6a على الهدف. لا ي��كن للبث إصلاح ذلك، لأن النسخ المتماثل المنطقي يسقط بهدوء تحديثات الصفوف التي لا توجد. لا يقوم الكتاب عمدًا بنسخ الجداول المؤقتة حقًا (pdn_session, lte_call). يتعارض COPY لتلك الجداول الساخنة (مفتاح مكرر) مع الكتابات المتزامنة على نظام حي ويؤدي إلى دورات تعطل لجداول التزامن. يتم إعادة ملئها من النسخ المتماثل المباشر وحركة المرور الحية بدلاً من ذلك.
تفاعلي (موصى به): تخلى عن المصدر. سيجد الكتاب بعد ذلك أي الأهداف فارغة، ويستجوب الأقران عن تلك التي تحتوي على بيانات، ويطلب منك الاختيار:
ansible-playbook -i hosts/Customer_Name/host_files/Production.yml \
util_playbooks/seed_hss_replication.yml \
--limit site-hss01,site-hss02
الأقران التي تتوفر منها بيانات للتهيئة:
1) dev-hss01 (10.4.10.142) - 838 مشترك
أدخل رقم المصدر الذي تريد التهيئة منه
صريح: قم بتسمية المصدر مباشرة. هذا يجبر على إعادة التهيئة حتى لو ��انت الهدف تحتوي بالفعل على بيانات (استخدمه للاسترداد):
ansible-playbook -i hosts/Customer_Name/host_files/Production.yml \
util_playbooks/seed_hss_replication.yml \
--limit site-hss01 \
-e "seed_source_name=dev-hss01 seed_source_host=10.4.10.142"
انظر HSS Replication Seed للحصول على مرجع كامل للمعلمات والسلوك.
يقوم seed_hss_replication.yml أيضًا بتوصيل الشبكة الكاملة بعد التهيئة: يقوم بتشغيل المصالحة النسخ المتماثل على كل عقدة (المنشورات، الاشتراكات، الفتحات) ويؤكد ذلك. يفضل تشغيله بدون --limit — يتم اكتشاف العقد الفارغة تلقائيًا كأهداف تهيئة، والعقد المملوءة كمصادر، ويتم توصيل كل عقدة في تمريرة واحدة. يضيق --limit كل من التهيئة والتوصيل، لذا فإن عقدة واحدة محدودة تترك الشبكة نصف موصولة؛ استخدمها فقط لإعادة تهيئة مستهدفة، ثم أعد التشغيل بدون --limit لتوصيل الباقي. قم بالتهيئة من مصدر واحد فقط. يفضل الخ��ار A لمجموعات البيانات الكبيرة جدًا.
تتم الخطوات اليدوية المعادلة على العقدة المستهدفة. أولاً، قم بإنشاء الاشتراك المباشر (لاحظ slot_name الصريح لكل رابط، انظر تسمية الكائنات). ثم قم بملء جداول الرئيس بأمان من حيث التعارض مع تخطي جداول الحالة الساخنة:
-- 1. بث جميع الجداول، بدون نسخ ضخم
DROP SUBSCRIPTION IF EXISTS sub_from_dev_hss01;
CREATE SUBSCRIPTION sub_from_dev_hss01
CONNECTION 'host=10.4.10.142 port=5432 dbname=omnihss user=hss password=<omnihss.database_password>'
PUBLICATION dev_hss01_pub
WITH (copy_data = false, origin = none,
slot_name = 'site_hss01_from_dev_hss01');
# 2. ملء جداول الرئيس فقط (تشغيل على الهدف؛ -t كل جدول باستثناء
# schema_migrations، pdn_session، lte_call - يجب تضمين subscriber_state،
# أو كل مشترك تم ملؤه يصبح يتيمًا: يشير subscriber_state_id الخاص به إلى صف لا يصل أبدًا، مما يكسر
# API/S6a، ولا يمكن للبث إصلاحه لأن النسخ المتماثل المنطقي
# يسقط بهدوء تحديثات الصفوف المفقودة).
# يجب أن يتم تحميلها بختم أصل النسخ المتماثل: origin=none
# تقوم الاشتراكات الموقعة بتصفية التغييرات الموقعة عند الناشر، لذا فإن الملء غير مرئي للشبكة.
# يتم فك تشفير التحميل غير الموقعة من WAL مثل أي كتابة محلية
# ويعكس الإدراج إلى الأقران الذين يحملون الصفوف بالفعل،
# مما يؤدي إلى تأخير عمال تطبيقهم بسبب مفتاح مكرر.
sudo -u postgres psql -d omnihss -c \
"SELECT pg_replication_origin_create('omnihss_seed_load');"
{ echo "SELECT pg_replication_origin_session_setup('omnihss_seed_load');"
PGPASSWORD=<pw> pg_dump -h 10.4.10.142 -U hss -d omnihss \
--data-only --inserts --on-conflict-do-nothing --disable-triggers \
-t subscriber -t subscriber_state -t key_set -t sim -t msisdn ... ; } \
| sudo -u postgres psql -d omnihss
sudo -u postgres psql -d omnihss -c \
"SELECT pg_replication_origin_drop('omnihss_seed_load');"
التحقق من النسخ المتماثل
تقوم الوظيفة بتشغيل فحص صحي تلقائيًا بعد الإعداد، ويمكن أيضًا تشغيلها بمفردها. يؤكد التحقق أن:
- كل اشتراك لديه عملية عامل حية.
- كل فتحة نسخ منطقية نشطة.
- تأخر WAL أقل من 100 ميجابايت لكل فتحة.
- حالة WAL لكل فتحة هي
reservedأوextended(ليسlost).
للتحقق من الصحة عند الطلب، أعد تشغيل وظيفة OmniHSS (يتم تشغيل التحقق في النهاية)، أو تحقق مباشرة على عقدة:
# عمال الاشتراك - يجب أن يكون pid غير فارغ لكل واحد
sudo -u postgres psql -d omnihss -c \
"SELECT subname, pid IS NOT NULL AS worker_alive FROM pg_stat_subscription;"
# فتحات النسخ - يجب أن تكون active صحيحة، wal_status محجوز/موسع
sudo -u postgres psql -d omnihss -c \
"SELECT slot_name, active, wal_status, \
pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), confirmed_flush_lsn)) AS lag \
FROM pg_replication_slots WHERE slot_type = 'logical';"
| العرض | المعنى |
|---|---|
worker_alive = false | عامل الاشتراك متوقف: الند غير قابل للوصول أو بيانات الاعتماد/سلسلة الاتصال خاطئة. |
active = false (فتحة) | لا يوجد مشترك يستهلك الفتحة: اشتراك الند متوقف أو تم إسقاطه. |
تأخر متزايد lag | الند بطيء أو الرابط تدهور. WAL يتراكم ويستهلك القرص. |
wal_status = lost | الفتحة تأخرت كثيرًا وتمت إزالة WAL بواسطة PostgreSQL. يجب عليك إعادة تهيئة الند (انظر تحميل عقدة جديدة بالبيانات). |
يتضمن تقرير الفحص الصحي (health_check.yml) أيضًا لوحة نسخ HSS Postgres للعقد التي تم تمكين النسخ فيها، مما يظهر حالة عامل كل اشتراك وحالة كل فتحة النشطة وحالة WAL في لمحة.
سلامة البيانات
لا يفرض تطبيق النسخ المنطقي مفاتيح خارجية. يعمل عامل التطبيق مع session_replication_role = replica، مما يقمع المشغلات الداخلية RI التي تنفذ قيود FOREIGN KEY. لذلك، لا يقوم PostgreSQL أبدًا بإعادة التحقق من صف يصل عبر النسخ مقابل والده. تعطي قيود FK لك سلامة لكل عقدة، وليس سلامة على مستوى الشبكة.
في شبكة نشطة-نشطة تفتح ثغرة لا يمكن لعقدة واحدة التقاطها:
- تقوم العقدة A بحذف
epc_profileX. تمرON DELETE RESTRICTلأنها لا تحتوي على مشترك محلي يشير إلى X في تلك اللحظة. - تشير العقدة B (أو خطوة التزويد) إلى المشترك 203 إلى X. يمر هذا لأن X لا يزال موجودًا على B.
- تتكرر كلا التغييرين وتطبق بدون فحوصات FK. تتقارب كل عقدة على "203 → X" و "X محذوف": مرجع عالق لم تنتهك FK الخاصة بأي عقدة محليًا.
يؤدي وجود subscriber.epc_profile_id عالق إلى عدم قدرة HSS على بناء بيانات الاشتراك لذلك المشترك. ثم تجيب HSS بـ DIAMETER_ERROR_USER_UNKNOWN (5001) على ULR/AIR، على الرغم من أن صف المشترك موجود ومفعل. يجعل نافذة المخطط قبل البيانات (أدناه) الأمر أكثر احتمالًا، لأن المعاملات المتجاوزة يمكن أن تفصل إنشاء/حذف الوالد عن إعادة توجيه الطفل.
الكشف (ليس التنفيذ)
سوف يؤدي فرض FKs على مسار التطبيق إلى إيقاف الشبكة عند أي شذوذ، لذا بدلاً من ذلك، نحن نكتشف وننبه. تقوم كل عقدة بتثبيت وظيفة SECURITY DEFINER، omnihss_fk_orphan_count()، التي تحسب كل FK عمود واحد يشير إلى والد مفقود عبر جميع الجداول. يقوم postgres_exporter باختيارها، وتنبه Grafana عندما تكون أكبر من صفر (انظر المقاييس).
قم بتشغيل المسح يدويًا في أي وقت:
sudo -u postgres psql -d omnihss -tAc "SELECT omnihss_fk_orphan_count();" # 0 = نظيف
لتحديد الصفوف المخالفة لمرجع محدد (مثال: المشتركون الذين يشيرون إلى ملف EPC غير موجود):
SELECT s.imsi, s.epc_profile_id
FROM subscriber s
LEFT JOIN epc_profile e ON e.id = s.epc_profile_id
WHERE s.epc_profile_id IS NOT NULL AND e.id IS NULL;
يمكن معالجة ذلك عن طريق إعادة توجيه الصف إلى والد صالح (تحديث على صف موجود يتكرر بشكل نظيف عبر الشبكة) أو إزالته.
منع انحراف المخطط
كان المحفز الجذري للحادث الذي حفز هذا القسم هو ترحيل المخطط الذي تم تطبيقه على عقدة واحدة بينما كانت أقرانها لا تزال على المخطط القديم، ثم كتابة بيانات جديدة ضد الحقول الجديدة. نشرت المصدر صفوفًا لم تتمكن أقران المخطط القديم من تطبيقها، مما تسبب في أخطاء تطبيق ومعاملات متجاوزة، وبالتالي تباين.
- قم بترحيل الشبكة بأكملها معًا. قم بتطبيق الترحيلات على كل عقدة OmniHSS قبل التزويد ضد الحقول الجديدة. لا تكتب بيانات المخطط الجديد بينما أي نظير متأخر.
- راقب الانحراف. تصدر العقدة
omnihss_schema_max_version/omnihss_schema_migration_countلكل عقدة. قارنها عبر الشبكة. العقدة المتأخرة عن أقرانها هي ترحيل نصف مطبق. - راقب عدادات الأخطاء. يعني ارتفاع
omnihss_subscription_error_apply_error_count/_sync_error_countأن عامل التطبيق يفشل (وربما يتجاوز). يتم تشغيل تنبيه "أخطاء تطبيق/مزامنة نسخ HSS" على هذا.
إزالة نظير
تؤدي إزالة نظير إلى إسقاط الاشتراك من ذلك النظير وإزالة إدخاله في pg_hba.conf. تبقى البيانات التي تم نسخها بالفعل؛ فقط التغييرات المستقبلية تتوقف عن التدفق. يجب تأكيد الإزالة بشكل صريح.
على العقدة التي تقوم بإزالة النظير منها:
DROP SUBSCRIPTION IF EXISTS sub_from_<peer_name>;
ثم قم بإزالة سطر (أسطر) النظير من pg_hba.conf وأعد تحميل PostgreSQL:
sudo -u postgres psql -c 'SELECT pg_reload_conf();'
لا يزال النظير الذي تتم إزالته يحتفظ باشتراكه إلى هذه العقدة. إذا كان يجب قطع الرابط بالكامل، قم بإزالة ذلك الاشتراك هناك أيضًا. ثم قم بإزالة العقدة من connected_omnihss ومجموعة hss حتى لا يعيد تشغيل الدور التالي إنشائها.
النسخ الاحتياطي والاستعادة
تستخدم النسخ ��لاحتياطي والاستعادة في OmniHSS تفريغات PostgreSQL القياسية:
| العملية | الكتابة | الملاحظات |
|---|---|---|
| النسخ الاحتياطي | services/backup.yml | ينتج hss_dump_<host>_<ts>.sql (قاعدة البيانات) و hss_<host>_<ts>.tar.gz (تكوين /etc/omnihss) تحت backups/<Site_Name>/. يستثني التفريغ المنشورات/الاشتراكات. |
| الاستعادة | util_playbooks/restore_hss.yml | يطلب تفريغ SQL و/أو أرشيف التكوين. يوقف OmniHSS، يأخذ نسخة احتياطية قبل الاستعادة، يحذف/يعيد إنشاء قاعدة البيانات، يستعيد، ويعيد التشغيل. |
انظر كتب التشغيل المساعدة لسير العمل الأوسع للنسخ الاحتياطي/الاستعادة.
استعادة عقدة إلى شبكة نشطة-نشطة
تقوم restore_hss.yml بإسقاط النسخ على العقدة التي تستعيدها: قبل أن تحذف وتعيد إنشاء قاعدة البيانات، تحذف اشتراكات تلك العقدة، المنشورات، والفجوات. لذا بعد الاستعادة، لا تحتوي العقدة على أية كائنات نسخ — يجب إعادة توصيل الشبكة، وإعادة توصيل النظير وحده ليس كافيًا (لا تزال العقدة المستعادة بحاجة إلى منشور خاص بها مرة أخرى). قاعدتان:
- استعد عقدة واحدة فقط. الاستعادة على عقدتين أو أكثر في وقت واحد تدمر الشبكة (
restore_hss.ymlتحذر من ذلك). استعد واحدة، ثم قم بتغذية البقية منها. - يجب أن تعمل جميع العقد بنفس إصدار OmniHSS قبل توصيل النسخ. يحمل النسخ المنطقي البيانات، وليس المخطط. تتحقق
CREATE SUBSCRIPTIONمن أن كل جدول في منشور الناشر موجود بالفعل على المشترك، لذا لا يمكن أن يتم الاشتراك في عقدة على إصدار أحدث (الذي يتضمن منشوره جدولًا تمت إضافته بواسطة ترحيل لاحق، مثلims_subscription) من نظير لا يزال على المخطط القديم — تفشل الاشتراك معrelation "public.<table>" does not existولا يظهر ذلك الاتجاه أبدًا. يجب أن يتطابق مخطط التفريغ أيضًا مع الإصدار المنفذ، أو ستنتهي العقدة المستعادة متقدمة على أقرانها.
إعادة بناء زوج نشط-نشط من الصفر:
# 1. قم بتزويد كلا الجهازين الافتراضيين، ثم قم بتثبيت OmniHSS + المخطط على كليهما بنفس
# الإصدار (مخطط متطابق، فارغ، تم ترحيله على كل منهما).
ansible-playbook -i hosts/<inv>/host_files/<site>.yml omnihss.yml
# 2. استعد البيانات على عقدة واحدة فقط (يجب أن يتطابق مخطط التفريغ مع إصدار الخطوة 1).
# هذا يمسح كائنات النسخ الخاصة بتلك العقدة؛ الخطوة 3 تعيد بناء الشبكة.
ansible-playbook -i hosts/<inv>/host_files/<site>.yml \
util_playbooks/restore_hss.yml --limit <site>-hss01
# 3. قم بتغذية العقدة الأخرى (العقد الأخرى) وَ توصيل الشبكة الثنائية الاتجاه بالكامل — لا تستخدم --limit.
# يتم ملء العقد الفارغة من العقدة المستعادة؛ يتم (إعادة) إنشاء المنشورات،
# الاشتراكات والفجوات على كل عقدة، ثم يتم التحقق منها.
ansible-playbook -i hosts/<inv>/host_files/<site>.yml \
util_playbooks/seed_hss_replication.yml
لا تنتهي بـ seed_hss_replication.yml --limit <peer>: --limit يحدد التوصيل أيضًا، لذا فإنه ينشئ فقط اشتراك النظير ويترك العقدة المستعادة بدون منشورها — شبكة نصف موصلة، ذات اتجاه واحد.
تؤكد validate_replication.yml (التي يتم تشغيلها تلقائيًا) الآن أن كل عقدة تشترك في كل نظير، لذا فإن النتيجة نصف الموصلة تفشل بصوت عالٍ بدلاً من الإبلاغ عن صحة.
المقاييس
تشغل كل عقدة OmniHSS postgres_exporter، مما يكشف عن مقاييس PostgreSQL (بما في ذلك النسخ) إلى Prometheus. السلاسل المفيدة لصحة النسخ:
المقياس: pg_replication_slots_active
النوع: Gauge
الوصف: ما إذا كانت كل فتحة نسخ منطقية لديها مستهلك نشط.
التسميات:
slot_name: فتحة النسخ (واحدة لكل نظير مشترك)
المقياس: pg_stat_replication_* / تأخر الفتحة
النوع: Gauge
الوصف: تأخر موقع WAL لكل فتحة. يظهر مدى تأخر نظير مستهلك.
استعلامات المثال:
# أي فتحة نسخ منطقية غير نشطة (تنبيه إذا كانت > 0)
count(pg_replication_slots_active == 0)
# يمكن التحقق من الاشتراكات التي يجب أن توجد مقابل العمال النشطين
# ضد مخرجات كتاب التشغيل للتحقق أثناء النشر.
مقاييس OmniHSS المخصصة
يصدر postgres_exporter على كل عقدة أيضًا سلاسل صحة النسخ وسلامة OmniHSS عبر ملف استعلام مخصص
(roles/omnihss/files/postgres_exporter_queries.yaml). يقوم Prometheus بجمع هذه
تحت وظيفة HSS Postgres. تدعم قواعد التنبيه في مجموعة تنبيهات HSS
(roles/monitoring/templates/grafana/rules/):
| المقياس | النوع | المعنى | التنبيه |
|---|---|---|---|
omnihss_subscription_worker_alive{subname} | Gauge | 1 إذا كان عامل التطبيق الوارد يعمل | HSS Replication Worker Down (< 1 لمدة 2m) |
omnihss_replication_slot_active{slot_name} | Gauge | 1 إذا كان نظير يستهلك الفتحة | HSS Replication Slot Inactive (< 1 لمدة 5m) |
omnihss_replication_slot_wal_status_code{slot_name} | Gauge | 0=محجوز 1=موسع 2=غير محجوز 3=مفقود | HSS Replication Slot WAL Lost (> 2) |
omnihss_replication_slot_lag_bytes{slot_name} | Gauge | بايتات WAL المحتفظ بها للفتحة | HSS Replication WAL Lag High (> 100 MB لمدة 10m) |
omnihss_subscription_error_apply_error_count{subname} | Counter | الأخطاء التراكمية لعامل التطبيق | HSS Replication Apply/Sync Errors (increase > 0) |
omnihss_subscription_error_sync_error_count{subname} | Counter | الأخطاء التراكمية لمزامنة الجداول | (نفس التنبيه) |
omnihss_integrity_fk_orphans | Gauge | الصفوف التي تحتوي على مفتاح خارجي عالق (يجب أن تكون 0) | HSS Data Integrity Orphans (> 0) |
omnihss_schema_max_version / omnihss_schema_migration_count | Gauge | علامة المياه العالية للترحيل المطبق / العدد | قارن عبر الشبكة لاكتشاف انحراف المخطط |
انظر المراقبة والرصد لخط أنابيب المقاييس ولوحات المعلومات.
استكشاف الأخطاء وإصلاحها
تبقى العقدة الجديدة فارغة بعد الانضمام
الأعراض: عمال النسخ نشطون والفجوات نشطة، لكن العقدة الجديدة لا تحتوي على (أو تحتوي على عدد قليل من) المشتركين.
الأسباب المحتملة:
- انضمت العقدة إلى شبكة مشغولة بالفعل ولم يتم تغذيتها أبدًا. تستخدم الاشتراكات
copy_data = false، لذا تصل فقط التغييرات بعد الانضمام.
الحل:
- قم بتغذية العقدة من نظير صحي. انظر تحميل عقدة جديدة بالبيانات.
عامل الاشتراك غير نشط
الأعراض: pid IS NULL لاشتراك في pg_stat_subscription.
الأسباب المحتملة:
- النظير غير قابل للوصول على منفذ PostgreSQL (جدار ناري / توجيه).
- عنوان IP للنظير مفقود من
pg_hba.confلهذه العقدة. - بيانات اعتماد خاطئة في سلسلة الاتصال (
database_username/database_passwordتختلف بين العقد).
الحل:
- تأكد من إمكانية الوصول TCP إلى النظير على
5432. - تحقق من ظهور النظير في
connected_omnihss(أو مجموعةhssالمحلية) وأعد تشغيل الوظيفة حتى يتم تحديثpg_hba.conf. - تأكد من أن
database_username/database_passwordمتطابقة عبر جميع العقد.
تظهر فتحة النسخ wal_status = lost
الأعراض: حالة wal_status لفتحة هي lost؛ النظير المقابل متأخر كثيرًا.
الأسباب المحتملة:
- كانت العقدة غير نشطة أو غير قابلة للوصول لفترة كافية بحيث تمت إزالة WAL المطلوبة.
الحل:
- أعد تغذية النظير المتأثر من عقدة صحية. انظر تحميل عقدة جديدة بالبيانات.
أخطاء المفتاح المكرر أثناء النسخة الأولية
الأعراض: أخطاء في تطبيق التغييرات مباشرة بعد إنشاء اشتراك مع
copy_data = true.
الأسباب المحتملة:
- تم تشغيل النسخة الأولية من أكثر من نظير، مما أدى إلى نسخ نفس الصفوف مرتين.
الحل:
- قم بتغذية من نظير واحد فقط مع
copy_data = true؛ احتفظ بجميع الاشتراكات الأخرى عندcopy_data = false.
تحديثات الحالة المتعارضة بين المواقع
الأعراض: يظهر صف الحالة (مثل subscriber_state) "يتأرجح" بين القيم المحددة في مواقع مختلفة.
الأسباب المحتملة:
- تحديثات متزامنة لنفس الصف في موقعين.
الحل: هذا متوقع ويتم التعامل معه. يحافظ مشغل "آخر كتابة تفوز" على التحديث مع أحدث updated_at. تأكد من مزامنة الساعات (NTP) عبر جميع المواقع بحيث يكون ترتيب updated_at ذا معنى.