عمليات النسخ المتماثل وعقد OmniHSS
تقوم OmniHSS بتخزين بيانات المشتركين، والمصادقة (AuC)، وبيانات IMS في قاعدة بيانات PostgreSQL محلية على كل عقدة. يتم الحفاظ على تزامن عدة عقد OmniHSS من خلال النسخ المتماثل المنطقي ثنائي الاتجاه لـ PostgreSQL، مما يشكل شبكة نشطة-نشطة: كل عقدة هي رئيسية كاملة للقراءة/الكتابة، وأي كتابة على أي عقدة تنتشر إلى جميع الآخرين. لا توجد عقدة رئيسية/احتياطية - يمكن لأي عقدة خدمة حركة مرور S6a و Cx/Dx وقبول التهيئة في أي وقت.
تتناول هذه الوثيقة نموذج النسخ المتماثل، كيفية إضافة عقدة OmniHSS جديدة وتحميلها بالبيانات، وكيفية التحقق من الصحة، وإصلاح، وإزالة الأقران.
جدول المحتويات
- نظرة عامة على الهندسة المعمارية
- كيفية اكتشاف الأقران
- التكوين
- إضافة عقدة OmniHSS جديدة
- تحميل عقدة جديدة بالبيانات
- التحقق من النسخ المتماثل
- سلامة البيانات
- إزالة نظير
- النسخ الاحتياطي والاستعادة
- الترحيل من HSS القديم
- المقاييس
- استكشاف الأخطاء وإصلاحها
نظرة عامة على الهندسة المعمارية
تعمل كل عقدة OmniHSS على تشغيل مثيل PostgreSQL خاص بها. كل عقدة تنشر جميع جداول التطبيق الخاصة بها و تشترك في نشر كل نظير. يتم منع حلقات النسخ المتماثل باستخدام origin = none، ويتم حل تعارضات الكتابة على جداول الحالة سريعة التغيير بواسطة آخر كتابة تفوز (LWW) من خلال مقارنة updated_at.
كل رابط أعلاه هو اشتراك واحد الاتجاه (واحد لكل اتجاه). بالنسبة لشبكة من N عقد، تحتفظ كل عقدة بـ N-1 اشتراكات و N-1 من فتحات النسخ المتماثل للنشر الخاصة بها يتم استهلاكها بواسطة الأقران.
ما الذي يتم نسخه
| فئة الجدول | أمثلة | معالجة التعارض |
|---|---|---|
| البيانات الرئيسية / المهيأة | subscriber, key_set (AuC), sim, msisdn | لا حاجة - يتم تهيئتها من مكان واحد في كل مرة |
| الحالة الديناميكية | subscriber_state, pdn_session, lte_call | آخر كتابة تفوز على updated_at |
| محاسبة الترحيل | schema_migrations | مستبعدة من النسخ المتماثل |
يغطي النشر كل جدول في مخطط public باستثناء schema_migrations (كل عقدة تقوم بتشغيل ترحيلاتها الخاصة بشكل مستقل). تضمن مشغلات LWW أنه عندما يتم تحديث نفس صف الحالة على عقدتين في وقت واحد، فإن أحدث updated_at هو الذي يفوز بدلاً من أي تحديث وصل آخر.
كيفية اكتشاف الأقران
عند تمكين النسخ المتماثل، يقوم دور OmniHSS ببناء قائمة الأقران الخاصة به تلقائيًا من مصدرين:
- المضيفون الآخرون في مجموعة
hssالمحلية - عقد OmniHSS المعرفة في نفس ملف الجرد/المضيف (على سبيل المثال، زوج محليhss01/hss02). لا تحتاج هذه إلى أن تكون مدرجة فيconnected_omnihss؛ يكفي أن تكون عضوية المجموعة. - قائمة
connected_omnihssفي ملف الأقران البعيد للموقع - عقد OmniHSS ��لمعرفة في ملف مضيف مختلف (مواقع أخرى). يمكن اكتشاف الأقران عبر الملفات هنا فقط، لأن جردًا واحدًا ليس لديه معرفة بمجموعةhssالخاصة بآخر.
ملاحظة: قائمة
connected_sites.hssالقديمة مخصصة لبرمجيات HSS القديمة وليس مستخدمة من قبل OmniHSS. تأتي أقران النسخ المتماثل لـ OmniHSS فقط من المجموعة المحليةhssبالإضافة إلىconnected_omnihss.
المجموعات المختلطة (القديمة + OmniHSS): يتم تصفية أقران المجموعة المحلية إلى المضيفين الذين هم مشاركون في النسخ المتماثل لـ OmniHSS - أولئك الذين تكون قيمة omnihss.replication.enabled لديهم true. إذا كانت مجموعة hss تحتوي أيضًا على صناديق HSS القديمة (برمجيات مختلفة)، قم بتعيين كتلة omnihss لكل مضيف على عقد OmniHSS فقط (يحتفظ مرجع YAML بها جافة) بدلاً من كونها متغير مجموعة، بحيث لا يتم التقاط المضيفين القدامى كأقران نسخ متماثل. يمكن لمجموعة OmniHSS المتجانسة تعيينه�� كمتغير مجموعة.
يستبعد الدور المضيف الحالي من قائمة الأقران الخاصة به تلقائيًا، لذا يمكن مشاركة نفس كتلة 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 المحتفظ به لفتحة متأخرة/عالقة. بعد ذلك، يتم إبطال الفتحة (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عند المطالبة، قدم المسار إلى النسخة الاحتياطية SQL من الخطوة 1 واترك مسار التكوين فارغًا (لدى العقدة الجديدة بالفعل تكوينها الخاص من تشغيل الدور).
-
تأكيد تدفق النسخ المتماثل. الآن تنطبق الاشتراكات الموجودة للعقدة الجديدة (
copy_data = false) التغييرات على الجزء العلوي من اللقطة المستعادة. قم بتشغيل التحقق أدناه.
نافذة الصيانة: هناك نافذة صغيرة بين النسخ واللحظة التي يلحق فيها النسخ المتماثل حيث لا تكون تغييرات التهيئة على الأقران موجودة بعد على العقدة الجديدة. تتغير بيانات المشتركين الرئيسية بشكل نادر، وتتعافى الحالة الديناميكية (
subscriber_state,pdn_session,lte_call) من حركة المرور الحية، لذا فإن نافذة النشاط المنخفضة كافية. تجنب تهيئة مشتركين جدد أثناء التزويد.
الخيار B - التزويد باستخدام كتاب التزويد (موصى به)
يقوم كتاب المرافق seed_hss_replication.yml بالتزويد من نظير مختار واحد دون عيوب النسخ الجماعي الخام. يعيد إنشاء الاشتراك كاشتراك فقط للبث (copy_data = false، لا يوجد جداول متزامنة) ثم يملأ الصفوف الموجودة في جدول الماستر بتحميل آمن من التعارض. subscriber_state هو جزء من التعبئة: فهو بيانات هيكلية 1:1 (كل مشترك يشير إلى واحد بواسطة FK، تم إنشاؤه مرة واحدة عند التهيئة)، وتخطيه يترك كل مشترك تم تعبئته يتيمًا - مما يكسر 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 للحصول على مرجع كامل للمعلمات والسلوك.
دائمًا استخدم --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;"
# فتحات النسخ المتماثل - يجب أن تكون النشطة صحيحة، حالة 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 (فتحة) | لا يوجد مشترك يستهلك الفتحة - اشتراك النظير معطل أو تم إسقاطه. |
| تأخر متزايد | النظير بطيء أو الرابط متدهور؛ يتراكم WAL ويستهلك القرص. |
wal_status = lost | تأخرت الفتحة كثيرًا وتمت إزالة WAL. يجب إعادة تزويد النظير مرة أخرى (انظر تحميل عقدة جديدة بالبيانات). |
تتضمن تقرير فحص الصحة (health_check.yml) أيضًا لوحة نسخ PostgreSQL لـ HSS للعقد مع تمكين النسخ المتماثل، تعرض حالة عامل كل اشتراك وحالة كل فتحة نشطة وحالة WAL في لمحة.
سلامة البيانات
لا تفرض النسخ المتماثل المنطقي المفاتيح الأجنبية. يعمل عامل التطبيق مع session_replication_role = replica، مما يقمع المشغلات الداخلية RI التي تنفذ قيود FOREIGN KEY. وبالتالي، فإن الصف الذي يصل عبر النسخ المتماثل لا يتم إعادة التحقق منه أبدًا ضد والده. توفر قيود FK لك سلامة لكل عقدة، وليس سلامة عبر الشبكة.
في شبكة نشطة-نشطة تفتح ثغرة لا يمكن لعقدة واحدة أن تلتقطها:
- تقوم العقدة A بحذف
epc_profileX - تمرON DELETE RESTRICTلأنها لا تحتوي على مشترك محلي يشير إلى X في تلك اللحظة. - تشير العقدة B (أو خطوة التهيئة) إلى المشترك 203 → X - تمر لأن X لا يزال موجودًا على B.
- تتكرر كلا التغييرات وتطبق دون فحوصات FK. تتقارب كل عقدة على "203 → X" و "X محذوف": مرجع معلق لم تنتهك أي FK محليًا.
يجعل subscriber.epc_profile_id المتدلي 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، يأخذ نسخة احتياطية قبل الاستعادة، يسقط/يعيد إنشاء قاعدة البيانات، يستعيد، ويعيد التشغيل. |
انظر كتب المرافق للحصول على سير العمل الأوسع للنسخ الاحتياطي/الاستعادة.
الترحيل من HSS القديم
عند استبدال برمجيات HSS القديمة (الإدخالات تحت connected_sites.hss) أو OmniHSS المدعومة من MySQL، يتم نقل البيانات عبر واجهة برمجة التطبيقات REST بدلاً من النسخ المتماثل SQL، لأن المخططات تختلف:
- يتم التعامل مع OmniHSS المدعومة من MySQL → OmniHSS PostgreSQL و محاذاة شبكة PyHSS بواسطة أدوات الترحيل المرسلة مع الدور (
roles/omnihss/files/). تقوم هذه بقراءة الكيانات من واجهة برمجة التطبيقات HSS المصدر وكتابتها إلى الهدف، مع تعيين معرفات صحيحة إلى UUIDs حتمية بحيث يتم الحفاظ على العلاقات بين المفاتيح الأجنبية، مع خيارات لتغيير معرفات (لدمجها في موقع يحتوي بالفعل على بيانات) ومحاذاة معرفات AuC/المشتركين مع شبكة PyHSS الإنتاجية.
بمجرد أن تكون البيانات في OmniHSS الهدف، يستخدم التزامن المستمر بين عقد OmniHSS النسخ المتماثل المنطقي الموضح أعلاه.
المقاييس
تشغل كل عقدة 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)، يتم جمعها تحت وظيفة HSS Postgres. تدعم هذه قواعد التنبيه في مجموعة تنبيهات HSS
(roles/monitoring/templates/grafana/rules/):
| المقياس | النوع | المعنى | التنبيه |
|---|---|---|---|
omnihss_subscription_worker_alive{subname} | Gauge | 1 إذا كانت عملية التطبيق الواردة تعمل | HSS Replication Worker Down (< 1 لمدة 2 دقيقة) |
omnihss_replication_slot_active{slot_name} | Gauge | 1 إذا كان نظير يستهلك الفتحة | HSS Replication Slot Inactive (< 1 لمدة 5 دقائق) |
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 لمدة 10 دقائق) |
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 ذا معنى.