في معماريات الاستناد إلى الأحداث الحديثة، تعتبر سلامة البيانات وإمكانية تتبعها أمراً بالغ الأهمية. غالباً ما تواجه قواعد البيانات العلائقية التقليدية صعوبة في التعامل مع معدل الكتابة العالي ومرونة المخطط المطلوبة للاستناد إلى الأحداث. لحسن الحظ، يوفر PostgreSQL مزيجاً قوياً من الميزات—تحديداً نوع البيانات JSONB وفك التشفير المنطقي (Logical Decoding)—التي تتيح للمهندسين بناء سجلات تدقيق غير قابلة للتغيير، تعتمد على الإضافة فقط، مع أداء ومرونة استثنائيين.
يستكشف هذا المقال كيفية الاستفادة من هذه الأدوات لإنشاء نظام تدقيق قوي يلتقط كل تغيير في الحالة دون قفل قاعدة البيانات أو التضحية بالأداء.
المشكلة الأساسية: التدقيق في الاستناد إلى الأحداث
يفرض الاستناد إلى الأحداث أن حالة التطبيق مشتقة من تسلسل من الأحداث. ولتلبية متطلبات الامتثال وتصحيح الأخطاء، يجب أن نضمن أن هذه الأحداث غير قابلة للتغيير. بمجرد كتابة الحدث، لا يمكن تعديله أو حذفه. يُعد نمط "الإضافة فقط" هذا مثالياً لأعمدة JSONB، التي يمكنها تخزين بيانات حمولة معقدة وغير منظمة بكفاءة ضمن إطار علائقي.
ومع ذلك، فإن مجرد تخزين بيانات JSON في جدول ليس كافياً. نحن بحاجة إلى آلية لالتقاط هذه الكتابات بشكل موثوق، ربما للمستهلكين النهائيين مثل مستودعات البيانات أو لوحات المعلومات في الوقت الفعلي، دون التأثير على زمن انتقال المعاملة الأساسية.
تصميم المخطط للأحداث غير القابلة للتغيير
أولاً، دعنا نحدد مخططاً يفرض عدم القابلية للتغيير. نستخدم قيداً فريداً على معرف الحدث والطابع الزمني لمنع التكرار، ونستبعد مشغلات التحديث لضمان أن السجل يعتمد على الإضافة فقط حقاً.
CREATE TABLE event_store (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
aggregate_id UUID NOT NULL,
event_type VARCHAR(50) NOT NULL,
payload JSONB NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- اختياري: فهرس للاستعلام بناءً على تاريخ الكيان
CREATE INDEX idx_event_store_aggregate
ON event_store (aggregate_id, created_at);
من خلال جعل payload من النوع JSONB، نكتسب القدرة على استعلام حقول محددة داخل الحدث دون فك تسلسل الكتل البرمجية بالكامل، وهو أمر بالغ الأهمية لتصحيح الأخطاء أو تصفية سجلات التدقيق.
الاستفادة من التكرار المنطقي لفصل المكونات
بينما يعد تخزين الأحداث الخطوة الأولى، فإن مشاركة هذه البيانات مع الأنظمة الأخرى هو حيث يتألق التكرار المنطقي. على عكس التكرار المادي، الذي ينسخ قاعدة البيانات بأكملها، يسمح لك التكرار المنطقي بالاشتراك في جداول محددة وتدفق التغييرات بتنسيق قابل للقراءة (غالباً JSON أو بروتوكول البuffers).
لتفعيل ذلك، يجب تكوين ملف postgresql.conf الخاص بك:
wal_level = logical
max_replication_slots = 10
max_wal_senders = 10
بمجرد التفعيل، يمكنك إنشاء نشرية تقوم بتدفق الأحداث إلى المستهلكين النهائيين:
PUBLICATION event_pub FOR TABLE event_store;
فوائد هذا النهج
- الأداء: يقرأ المستهلكون النهائيون من سجل WAL (سجل الكتابة المسبق) بشكل غير متزامن. يضيف هذا عبئاً ضئيلاً جداً على مسار الكتابة الأساسي.
- تحمل الأعطال: إذا انقطع الاتصال بالمستهلك، يمكنه إعادة تشغيل سجل WAL من آخر موضع تم استهلاكه، مما يضمن عدم فقدان أي أحداث.
- فصل المكونات: يمكنك وجود عدة مستهلكين (مثل مؤشر Elasticsearch، أو منتج Kafka، أو محمل مستودع البيانات) دون التأثير على بعضهم البعض.
التنفيذ العملي: قراءة سجل WAL
يمكن للمطورين استخدام مكتبات مثل pgoutput في Java/Go أو psycopg2 مع إضافات فك التشفير المنطقي في Python لاستهلاك هذه التدفقات. تصل البيانات بتنسيق ي映射 مباشرة إلى مخططك، مما يجعل فك التسلسل أمراً سهلاً.
على سبيل المثال، قد يتلقى المستهلك رسالة مثل هذه:
{
"operation": "INSERT",
"table": "event_store",
"tuple": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"aggregate_id": "b2c1e9f0-...",
"event_type": "OrderPlaced",
"payload": {"item": "Widget", "qty": 1},
"created_at": "2023-10-27T10:00:00Z"
}
}
الخاتمة
يوفر الجمع بين مرونة JSONB في PostgreSQL والتكرار المنطقي أساساً مجرباً وخالقاً لسجلات التدقيق غير القابلة للتغيير في الأنظمة المعتمدة على الأحداث. يتيح لك ذلك الحفاظ على اتساق قوي في بياناتك الأساسية مع تدفق التغييرات بسهولة إلى الأنظمة الثانوية. هذه المعمارية قابلة للتوسع، ومرنة، وتستفيد من الناضج للنظام البيئي لـ PostgreSQL للتعامل مع تعقيدات هندسة البيانات الحديثة.
ابدأ بشكل صغير من خلال تنفيذ المخطط، ثم قم بدمج فتحة تكرار منطقية لتغذية مستهلكك الأول. النتيجة هي نظام سهل الصيانة وقوي بما يكفي للتعامل مع متطلبات التدقيق على نطاق الإنتاج.