الفكرة المجنونة
ماذا لو قمنا ببناء قائمة انتظار الرسائل باستخدام MariaDB فقط؟ ليس كافكا، وليس RabbitMQ، وليس Redis Streams. فقط MariaDB ومحركات التخزين الخاصة به والنسخ المتماثل لـ binlog.
إنه تمرين فكري، وإثبات للمفهوم. الهدف ليس استبدال حلول المراسلة التي أثبتت جدواها، ولكن إظهار مرونة بنية MariaDB / MySQL واستكشاف الأنماط غير المعروفة.
بنية MMQ
يعتمد MMQ (MariaDB قائمة انتظار الرسائل) على ثلاثة مكونات أصلية:
- محرك Blackhole: محرك تخزين يقبل الإدخالات ولكنه لا يخزن أي شيء. "تختفي" البيانات — إلا أنه يتم حفظها في السجل.
- Binlog replication: آلية النسخ المتماثل الأصلية لـ MariaDB والتي تنشر الأحداث من خادم إلى آخر.
- الجداول InnoDB + المشغلات: لاستهلاك الرسائل وتتبعها.
المنتج (الناشر)
يحتوي الخادم المنتج على جدول Blackhole الذي يعمل كنقطة دخول:
CREATE TABLE message_queue (
msg_id BIGINT NOT NULL,
topic VARCHAR(255) NOT NULL,
payload JSON NOT NULL,
created_at DATETIME(6) DEFAULT NOW(6)
) ENGINE=Blackhole;
عندما ينشر التطبيق رسالة:
INSERT INTO message_queue (msg_id, topic, payload)
VALUES (
NEXT VALUE FOR msg_sequence,
'order.created',
'{"order_id": 12345, "customer": "acme", "total": 99.99}'
);
محرك Blackhole لا يكتب أي شيء على القرص. ولكن يتم تسجيل INSERT في سجل الخادم. هذا هو سحر Blackhole: فهو يشارك في binlog دون استهلاك مساحة التخزين.
تسلسلات للمعرفات
MariaDB يدعم التسلسلات (منذ الإصدار 10.3)، والتي توفر معرفات فريدة دون تكلفة القفل AUTO_INCREMENT:
CREATE SEQUENCE msg_sequence
START WITH 1
INCREMENT BY 1
CACHE 1000;
يقوم CACHE 1000 بتخصيص 1000 قيمة مسبقًا في الذاكرة، مما يقلل من الوصول إلى القرص والأقفال.
الوسيط (التتابع)
الوسيط هو خادم MariaDB تم تكوينه ليكون تابعًا للمنتج. يتلقى أحداث binlog ويكررها. هذه هي آلية التوزيع.
بالنسبة للنشرة المتشعبة (رسالة إلى العديد من المستهلكين)، يمكن أن يكون لدينا عدة تابعين من نفس السيد - يتلقى كل تابع نسخة مستقلة من جميع الرسائل.
Producteur (Blackhole) → binlog → Broker 1 (slave)
→ Broker 2 (slave)
→ Broker 3 (slave)
المستهلك
لدى كل مستهلك جدول InnoDB يخزن فيه الرسائل المستلمة وآلية مراقبة الاستهلاك:
CREATE TABLE consumed_messages (
msg_id BIGINT PRIMARY KEY,
topic VARCHAR(255),
payload JSON,
created_at DATETIME(6),
consumed_at DATETIME(6) DEFAULT NULL,
consumer_id VARCHAR(100) DEFAULT NULL
) ENGINE=InnoDB;
يقوم المشغل بتحويل الإدخالات المنسوخة إلى خطوط قابلة للاستخدام:
CREATE TRIGGER trg_message_arrived
BEFORE INSERT ON message_queue
FOR EACH ROW
BEGIN
INSERT INTO consumed_messages (msg_id, topic, payload, created_at)
VALUES (NEW.msg_id, NEW.topic, NEW.payload, NEW.created_at);
END;
الاستهلاك يتم بطلب ذري :
UPDATE consumed_messages
SET consumed_at = NOW(6),
consumer_id = 'worker-01'
WHERE consumed_at IS NULL
AND topic = 'order.created'
ORDER BY msg_id ASC
LIMIT 1;
يضمن LIMIT 1 مع UPDATE الذري أن يقوم مستهلك واحد فقط بمعالجة كل رسالة (لا يوجد استهلاك مزدوج).
الرسائل في JSON
يسمح لك تنسيق JSON الأصلي لـ MariaDB (منذ 10.2) بتنظيم الرسائل ذات الحمولات الغنية:
-- Publier un événement complexe
INSERT INTO message_queue (msg_id, topic, payload) VALUES (
NEXT VALUE FOR msg_sequence,
'user.profile.updated',
JSON_OBJECT(
'user_id', 42,
'changes', JSON_ARRAY(
JSON_OBJECT('field', 'email', 'old', 'old@mail.com', 'new', 'new@mail.com'),
JSON_OBJECT('field', 'name', 'old', 'John', 'new', 'Jonathan')
),
'timestamp', NOW(6)
)
);
الحدود (وهناك الكثير)
لنكن واضحين: MMQ هو مفهوم، وليس حلاً جاهزًا للإنتاج.
لا يوجد ضمان للتسليم الموثوق. إذا فشل النسخ المتماثل، يتم فقدان الرسائل (أو تأخيرها). لا توجد آلية إعادة المحاولة الأصلية.
لا يوجد تقسيم. تمر جميع الرسائل عبر سجل بيانات واحد. لا يوجد توزيع حسب الموضوع مثل كافكا.
لا يوجد إعادة تشغيل. بمجرد استهلاك الرسالة، لا يمكن إعادة تشغيلها بسهولة (ما لم يتم الاحتفاظ بالسجلات الثنائية على المنتج).
زمن وصول النسخ المتماثل. يضيف زمن وصول النسخ المتماثل تأخيرًا بين نشر الرسالة ومدى توفرها. يعد هذا مقبولًا للاستخدام غير المتزامن، ولكن ليس للوقت الفعلي.
لا يوجد إقرار موزع. لا يعرف المنتج ما إذا كان المستهلك قد قام بمعالجة الرسالة أم لا.
لماذا هو مثير للاهتمام على أي حال
على الرغم من محدودياته، يوضح هذا النمط مفاهيم مهمة:
-
binlog كتدفق حدث. binlog الخاص بـ MariaDB / MySQL هو تدفق أحداث منظم ومتين وقابل للتكرار. هذا قريب من الناحية المفاهيمية من سجل كافكا.
-
محرك Blackhole كمحول. يتيح لك Blackhole "النشر" دون تخزين، وذلك باستخدام binlog كقناة نقل.
-
النسخ المتماثل كآلية توزيع. يوفر النسخ المتماثل متعدد التابع توزيعًا أصليًا بدون تكوين إضافي.
-
قاعدة البيانات كبنية تحتية متعددة الاستخدامات. إذا كان لديك بالفعل MariaDB قيد الإنتاج، فهذا يعني أن لديك بالفعل البنية الأساسية للمراسلة البسيطة.
بالنسبة لحالات الاستخدام البسيطة - الإشعارات الداخلية بين الخدمات، وتدقيق الأحداث، وتكرار الأحداث بين المواقع - قد يكون MMQ كافيًا دون إضافة مكون بنية أساسية إضافي.
الخلاصة
MariaDB كقائمة انتظار للرسائل: فكرة مجنونة، وإثبات ممتع للمفهوم، وعرض لمرونة محرك Blackhole + النسخ المتماثل لـ binlog. لا تستخدمه في الإنتاج للرسائل الهامة. لكن ضع هذا المفهوم في الاعتبار - في بعض الأحيان تكون أفضل هندسة معمارية هي تلك التي تستخدم ما لديك بالفعل.
تم نشر هذه المقالة في الأصل على متوسط.
تعليقات (0)
لا توجد تعليقات حتى الآن.
اترك تعليقا