غيّر تدفق أحداث Kafka تصميم الأنظمة عبر معاملة الأحداث كسجل مرتب. تعرّف متى يكفي طابور بسيط ومتى يجدي اتباع نهج قائم على السجل.

تبدأ معظم المنتجات بتكاملات بسيطة نقطة-إلى-نقطة: النظام أ يستدعي النظام ب، أو سكربت صغير ينسخ بيانات من مكان إلى آخر. يعمل ذلك حتى يكبر المنتج، وتتفرّق الفرق، ويزداد عدد الاتصالات. قريبًا كل تغيير يحتاج تنسيقًا عبر خدمات متعددة، لأن حقلًا صغيرًا أو تحديث حالة يمكن أن يترتب عليه سلسلة من التبعيات.
السرعة عادةً هي أول ما ينكسر. إضافة ميزة جديدة تعني تحديث تكاملات متعددة، إعادة نشر عدة خدمات، والأمل بألا يكون هناك اعتماد على السلوك القديم.
ثم يصبح تصحيح الأخطاء مؤلمًا. عندما يظهر شيء خاطئ في واجهة المستخدم، يصعب الإجابة عن أسئلة أساسية: ما الذي حدث، بأي ترتيب، وأي نظام كتب القيمة التي تراها؟
القطعة المفقودة غالبًا هي مسار تدقيق. إذا كانت البيانات تُدفَع مباشرة من قاعدة بيانات إلى أخرى (أو تُحوَّل في الطريق)، تفقد التاريخ. قد ترى الحالة النهائية، لكنك لا ترى تسلسل الأحداث الذي أوصل إليها. مراجعات الحوادث ودعم العملاء يتأثران لأنك لا تستطيع إعادة تشغيل الماضي للتأكد مما تغيّر ولماذا.
هنا يبدأ أيضًا جدال “مَنْ يملك الحقيقة”. يقول فريق: “خدمة الفوترة هي مصدر الحقيقة.” ويقول آخر: “خدمة الطلبات هي.” في الواقع، كل نظام لديه رؤية جزئية، والتكاملات نقطة-إلى-نقطة تحوّل ذلك الخلاف إلى احتكاك يومي.
مثال بسيط: تم إنشاء طلب، ثم دُفِع، ثم رُدَّ. إذا كانت ثلاث خدمات تُحدِّث بعضها البعض مباشرة، يمكن أن ينتهي كل واحد بقصة مختلفة عند حدوث إعادة المحاولة، انقضاء مهلة، أو إصلاح يدوي.
هذا يقود إلى السؤال التصميمي الأساسي خلف تدفق أحداث Kafka: هل تحتاج فقط إلى نقل العمل من مكان لآخر (طابور)، أم تحتاج إلى سجل مشترك ودائم لما حدث يمكن للعديد من الأنظمة قراءته وإعادة تشغيله والثقة به (سجل)؟ الإجابة تغيّر الطريقة التي تبني بها، تصحّح، وتطوّر نظامك.
ساهم Jay Kreps في تشكيل Kafka، والأهم من ذلك، في تغيير الطريقة التي تفكر بها الفرق حول حركة البيانات. التحوّل المفيد هو ذهني: توقف عن معاملة الرسائل كعمليات تسليم منفردة، وابدأ في معاملة نشاط النظام كسجل.
الفكرة الأساسية بسيطة. نمذج التغييرات المهمة كسيل من الحقائق غير القابلة للتغيير:
كل حدث حقيقة لا يجب تعديلها بعد وقوعها. إذا تغيّر شيء لاحقًا، تضيف حدثًا جديدًا يعلن الحقيقة الجديدة. مع الوقت، تشكّل تلك الحقائق سجلًّا: تاريخ إلحاقي لا يغيّر.
هنا يختلف تدفق أحداث Kafka عن كثير من إعدادات الرسائل الأساسية. الكثير من الطوابير مبنية على مبدأ “أرسلها، عالجها، احذفها.” هذا مناسب عندما يكون العمل مجرد تسليم. وجهة النظر القائمة على السجل تقول: “احتفظ بالتاريخ حتى يتمكن العديد من المستهلكين من استخدامه، الآن وفيما بعد.”
إعادة تشغيل التاريخ هي القوة العملية العظمى.
إذا كانت تقاريرك خاطئة، يمكنك إعادة تشغيل نفس تاريخ الأحداث عبر عملية تحليلات ثابتة ورؤية أين تغيّرت الأرقام. إذا تسبّب عطل في إرسال رسائل خاطئة، يمكنك إعادة تشغيل الأحداث في بيئة اختبار واستنساخ التسلسل الزمني الدقيق. إذا كانت ميزة جديدة تحتاج بيانات سابقة، يمكنك بناء مستهلك جديد يبدأ من البداية ويلحق بالركب بوتيرته الخاصة.
مثال ملموس: تخيل أنك تضيف فحوصات احتيال بعد أن عالجت شهورًا من المدفوعات. مع سجل لمدفوعات وأحداث الحساب، يمكنك إعادة تشغيل الماضي لتدريب أو معايرة القواعد على تسلسلات حقيقية، حساب درجات المخاطر للمعاملات القديمة، وملء أحداث “fraud_review_requested” دون إعادة كتابة قاعدة البيانات.
لاحظ ماذا يجبرك هذا على فعله. النهج القائم على السجل يدفعك لتسمية الأحداث بوضوح، الحفاظ على ثباتها، وقبول أن فرقًا وخدمات متعددة ستعتمد عليها. كما يفرض أسئلة مفيدة: ما مصدر الحقيقة؟ ماذا يعني هذا الحدث على المدى البعيد؟ ماذا نفعل عندما نخطئ؟
القيمة ليست في الشخصية؛ القيمة في إدراك أن السجل المشترك يمكن أن يصبح ذاكرة نظامك، والذاكرة هي ما يسمح للأنظمة بالنمو دون أن تنهار كلما أضفت مستهلكًا جديدًا.
طابور الرسائل يشبه قائمة مهام لبرنامجك. يضع المنتجون العمل في القائمة، يلتقط المستهلكون العنصر التالي، ينفّذون العمل، ويُحذف العنصر. الهدف الأساسي هو إنجاز كل مهمة مرة واحدة، بأسرع ما يمكن.
السجل مختلف. هو سجل مرتب من الحقائق التي حدثت، محفوظ بتسلسل دائم. المستهلكون لا “يأخذون” الأحداث بعيدًا. يقرأون السجل بوتيرتهم الخاصة، ويمكنهم قراءته مجددًا لاحقًا. في تدفق أحداث Kafka، هذا السجل هو الفكرة الجوهرية.
طريقة عملية للتذكّر:
الاحتفاظ يغيّر التصميم. مع الطابور، إذا احتجت لاحقًا ميزة تعتمد على رسائل قديمة (تحليلات، فحوصات احتيال، إعادة تشغيل بعد خطأ)، غالبًا ستضيف قاعدة بيانات منفصلة أو تبدأ بالتقاط نسخ إضافية في مكان آخر. مع السجل، إعادة التشغيل طبيعية: يمكنك إعادة بناء عرض مشتق بقراءة من البداية (أو من نقطة تحقق معروفة).
الانتشار لعدة مستهلكين فرق كبير أيضًا. تخيّل خدمة الخروج تُصدر "OrderPlaced". مع طابور، عادةً تختار مجموعة عمال واحدة لمعالجتها، أو تُضاعِف العمل عبر طوابير متعددة. مع السجل، يمكن للفواتير والبريد والمخزون وفهرسة البحث والتحليلات كلها قراءة نفس سيل الأحداث بشكل مستقل. كل فريق يتحرك بوتيرته الخاصة، وإضافة مستهلك لاحقًا لا تتطلب تغيير المنتج.
إذاً النموذج الذهني واضح: استخدم الطابور عندما تنقل مهام؛ استخدم السجل عندما تسجل أحداثًا قد تحتاج عدة أجزاء من الشركة لقراءتها الآن أو لاحقًا.
يغيّر تدفق الأحداث سؤال الافتراضي. بدلًا من السؤال "لمن أرسل هذه الرسالة؟" تبدأ بتسجيل "ماذا حدث للتو؟" هذا يبدو بسيطًا، لكنه يغيّر كيفية نمذجة نظامك.
تنشر حقائق مثل OrderPlaced أو PaymentFailed، وتقرر أجزاء أخرى من النظام إن كانت ستتفاعل ومتى وكيف.
مع تدفق أحداث Kafka، يتوقّف المنتجون عن الحاجة إلى قائمة تكاملات مباشرة. يمكن لخدمة الخروج نشر حدث واحد، ولا تحتاج لمعرفة إن كانت التحليلات أو البريد أو فحوصات الاحتيال أو خدمة التوصية المستقبلية ستستخدمه. يمكن أن يظهر مستهلكون جدد لاحقًا، ويمكن إيقاف القديمة مؤقتًا، والمنتج يظل يتصرف بنفس الطريقة.
هذا يغيّر أيضًا كيفية الاسترداد من الأخطاء. في عالم قائم على الرسائل فقط، عندما يفوت مستهلك شيئًا أو يكون فيه خطأ، غالبًا ما تكون البيانات "مفقودة" ما لم تبني نسخًا احتياطية مخصصة. مع السجل، يمكنك إصلاح الكود وإعادة تشغيل التاريخ لإعادة بناء الحالة الصحيحة. هذا غالبًا أفضل من التعديلات اليدوية على قواعد البيانات أو السكربتات الأحادية التي لا يثق بها أحد.
على أرض الواقع، يظهر التحوّل في أمور موثوقة: تعامل مع الأحداث كسجل دائم، أضف ميزات بالاشتراك بدلاً من تعديل المنتجين، أعد بناء نماذج القراءة (فهرس البحث، لوحات القيادة) من الصفر، وتحصل على جداول زمنية أوضح لما حدث عبر الخدمات.
تتحسن المراقبة لأن سجل الأحداث يصبح مرجعًا مشتركًا. عندما يحدث خطأ، يمكنك تتبع تسلسل أعمال: إنشاء الطلب، حجز المخزون، إعادة محاولة الدفع، جدولة الشحن. ذلك التسلسل غالبًا أسهل للفهم من سجلات تطبيق متناثرة لأنه يركز على الحقائق التجارية.
مثال ملموس: إذا تسبب خطأ في تسعير الخصم بخطأ لمدّة ساعتين، يمكنك نشر إصلاح وإعادة تشغيل الأحداث المتأثرة لإعادة حساب الإجماليات، تحديث الفواتير، وتحديث التحليلات. تقوم بتصحيح النتائج عن طريق إعادة استنتاجها، لا عن طريق التخمين أي جداول يجب تعديلها يدويًا.
الطابور البسيط هو الأداة الصحيحة عندما تنقل العمل، وليس عندما تبني سجلًا طويل الأمد. الهدف هو تسليم مهمة للعامل، تشغيلها، ثم نسيانها. إذا لم يحتاج أحد لإعادة تشغيل الماضي، أو فحص الأحداث القديمة، أو إضافة مستهلكين لاحقًا، يبقي الطابور الأمور أبسط.
الطوابير تتألق في مهام الخلفية: إرسال رسائل تسجيل، تغيير حجم الصور بعد الرفع، توليد تقرير ليلي، أو استدعاء واجهة برمجة تطبيقات خارجية بطيئة. في هذه الحالات تكون الرسالة مجرد تذكرة عمل. بمجرد أن ينتهي العامل، تكون التذكرة قد أدّت دورها.
الطابور يناسب أيضًا نموذج الملكية المعتاد: مجموعة مستهلكين واحدة مسؤولة عن إنجاز العمل، ولا يتوقع من خدمات أخرى قراءة نفس الرسالة بشكل مستقل.
الطابور عادةً يكفي عندما تنطبق معظم ما يلي:
مثال: منتج يرفع صور المستخدمين. التطبيق يكتب مهمة "تغيير حجم الصورة" إلى طابور. العامل A يلتقطها، ينشئ مصغرات، يخزنها، ويعلّم المهمة منجَزَة. إذا عملت المهمة مرتين، فالنتيجة نفسها (قابلة للتكرار)، لذا التوصيل بنظام "مرة واحدة على الأقل" مقبول. لا خدمة أخرى تحتاج لقراءة تلك المهمة لاحقًا.
إذا بدأت احتياجاتك تنجرف نحو الحقائق المشتركة (مستهلكون متعددون)، إعادة التشغيل، التدقيق، أو “ماذا كان يعتقد النظام الأسبوع الماضي؟”، هنا يبدأ تدفق أحداث Kafka ونهج السجل في جلب القيمة.
يدفع النظام القائم على السجل ثماره عندما تتوقف الأحداث عن كونها رسالة لمرة واحدة وتصبح تاريخًا مشتركًا. بدلًا من "أرسل وانسى"، تحتفظ بسجل مرتب يمكن لفرق عديدة قراءته الآن أو لاحقًا وبوتيرة خاصة بها.
الإشارة الأوضح هي وجود مستهلكين متعددين. حدث واحد مثل OrderPlaced يمكن أن يغذي الفوترة، البريد، فحوصات الاحتيال، فهرسة البحث، والتحليلات. مع السجل، يقرأ كل مستهلك نفس السيل بشكل مستقل. لا تحتاج لبناء خط أنابيب تفرّع مخصص أو تنسيق من يحصل على الرسالة أولًا.
فائدة أخرى هي القدرة على الإجابة عن سؤال "ماذا كنا نعرف آنذاك؟" إذا احتجت لاسترداد نزاع عميل على رسم، أو أن توصية كانت خاطئة، يجعل التاريخ الإلحاقي من الممكن إعادة تشغيل الحقائق كما وصلت. من الصعب إضافة هذا الأثر التدقيقي إلى طابور بسيط لاحقًا.
تحصل أيضًا على طريقة عملية لإضافة ميزات دون إعادة كتابة القديمة. إذا أضفت صفحة "حالة الشحن" بعد أشهر، يمكن لخدمة جديدة الاشتراك وملء بياناتها من التاريخ الموجود لبناء حالتها، بدلاً من طلب تصديرات من أنظمة سابقة.
نهج قائم على السجل غالبًا ما يكون مجديًا عندما تعرف أحد أو أكثر من هذه الاحتياجات:
نمط شائع: منتج يبدأ بالطلبات والبريد. لاحقًا، تريد المالية تقارير عائد، والمنتج يرغب في قنوات التحويل، والعمليات تريد لوحة حية. إذا أجبرت كل حاجة جديدة على نسخ البيانات عبر خط أنابيب جديد، تظهر التكاليف بسرعة. السجل المشترك يتيح للفرق البناء على نفس مصدر الحقيقة حتى مع نمو النظام وتغير أشكال الأحداث.
اختيار بين طابور بسيط ونهج قائم على السجل يصبح أسهل عندما تعامل الأمر كقرار منتجي. ابدأ بما يجب أن يكون صحيحًا بعد سنة، لا بما يعمل هذا الأسبوع.
ارسم الناشرين والمستهلكين. دوّن من ينشئ الأحداث ومن يقرأها اليوم، ثم أضف المستهلكين المحتملين في المستقبل (تحليلات، فهرسة، فحوصات احتيال، إشعارات). إذا توقعت أن فرقًا كثيرة ستقرأ نفس الأحداث بشكل مستقل، يبدأ السجل أن يكون منطقيًا.
اسأل إن كنت ستحتاج لإعادة قراءة التاريخ. كن محددًا بالسبب: إعادة التشغيل بعد خطأ، ملء رجعي، أو مستهلكون يقرأون بسرعات مختلفة. الطوابير رائعة لتسليم المهمة مرة واحدة. السجلات أفضل عندما تريد سجلًا يمكنك إعادة تشغيله.
حدّد ماذا يعني “انتهى”. لبعض سير العمل، الانتهاء يعني "المهمة نفذت" (إرسال بريد، تغيير حجم صورة). لآخرين، الانتهاء يعني "الحدث حقيقة دائمة" (تم تقديم طلب، تم تفويض دفع). الحقائق الدائمة تدفعك نحو السجل.
اختر توقعات التسليم وقرّر كيف تتعامل مع التكرارات. التوصيل على الأقل مرة شائع، ما يعني إمكانية التكرارات. إذا كان التكرار قد يضر (شحن مزدوج لبطاقة)، خطط للهوية: خزن معرف الحدث المعالج، استخدم قيود فريدة، أو اجعل التحديثات آمنة للتكرار.
ابدأ بشريحة رقيقة. اختر سيل أحداث واحد سهل الفهم وانمِ منه. إذا اخترت Kafka، حافظ على الموضوع الأول مركزًا، سمّ الأحداث بوضوح، وتجنّب خلط أنواع أحداث غير مرتبطة.
مثال ملموس: إذا كان OrderPlaced سيغذي لاحقًا الشحن، الفوترة، الدعم، والتحليلات، يسمح لك السجل لكل فريق بالقراءة بوتيرته وإعادة التشغيل بعد الأخطاء. إذا كل ما تحتاجه هو عامل خلفي لإرسال إيصال، فغالبًا يكفي الطابور البسيط.
تخيّل متجرًا إلكترونيًا صغيرًا. في البداية يحتاج فقط لقبول الطلبات، تحصيل البطاقة، وإنشاء طلب شحن. أسهل نسخة هي مهمة خلفية واحدة تعمل بعد الخروج: "اعالج الطلب". تتصل بواجهة الدفع، تحدّث صف الطلب في قاعدة البيانات، ثم تستدعي الشحن.
نمط الطابور يعمل جيدًا عندما يكون هناك سير عمل واضح واحد، مستهلك واحد فقط، وإعادة المحاولة وصناديق الموت تغطي معظم حالات الفشل.
يبدأ المعاناة مع نمو المتجر. يريد الدعم تحديثات تلقائية "أين طلبي؟". تريد المالية أرقام إيرادات يومية. يريد فريق المنتج رسائل بريدية للعملاء. يجب أن يحدث فحص احتيال قبل الشحن. مع مهمة "اعلاج الطلب" المفردة، ستجد نفسك تعدّل نفس العامل مرارًا، تضيف فروعًا، وتعرّض التدفق الأساسي لمخاطر أخطاء جديدة.
مع نهج قائم على السجل، ينتج الخروج حقائق صغيرة كأحداث، ويمكن لكل فريق البناء عليها. الأحداث النموذجية قد تكون:
OrderPlacedPaymentConfirmedItemShippedRefundIssuedالتغيير الرئيسي هو الملكية. خدمة الخروج تمتلك OrderPlaced. خدمة المدفوعات تمتلك PaymentConfirmed. الشحن يمتلك ItemShipped. لاحقًا يمكن أن يظهر مستهلكون جدد دون تغيير المنتج: خدمة احتيال تقرأ OrderPlaced وPaymentConfirmed لتقييم المخاطر، خدمة بريد ترسل إيصالات، التحليلات تبني قنوات، وأدوات الدعم تُكوّن جدولًا زمنيًا لما حدث.
هنا يدفع تدفق أحداث Kafka ثماره: السجل يحتفظ بالتاريخ، لذا يمكن للمستهلكين الجدد إعادة الإرجاع والالتحاق من البداية (أو من نقطة معروفة) بدلاً من مطالبة كل نظام علوي بإضافة ويب هوك آخر.
السجل لا يحل محل قاعدة بياناتك. لا تزال بحاجة لقاعدة بيانات للحالة الحالية: آخر حالة للطلب، سجل العميل، أعداد المخزون، وقواعد إجرائية (مثل "لا تشحن ما لم يتم تأكيد الدفع"). فكّر بالسجل كسجل التغييرات وقاعدة البيانات كمكان تسأل فيه "ماذا هو الصحيح الآن؟".
قد يجعل تدفق الأحداث الأنظمة تبدو أنظف، لكن بعض الأخطاء الشائعة قد تمحو الفوائد بسرعة. معظمها ينبع من معاملة سجل الحدث كجهاز تحكّم عن بعد بدلًا من كونه سجلًا.
فخ متكرر هو كتابة الأحداث كأوامر، مثل "SendWelcomeEmail" أو "ChargeCardNow". هذا يجعل المستهلكات مترابطة بشدة مع نيتك. تعمل الأحداث بشكل أفضل كحقائق: "UserSignedUp" أو "PaymentAuthorized". الحقائق تصمد عبر الزمن. يمكن للفرق الجديدة إعادة استخدامها لاحقًا دون التخمين بشأن ما قصدته.
التكرارات وإعادة المحاولة مصدر ألم آخر كبير. في الأنظمة الحقيقية، يعيد المنتجون المحاولة ويعيد المستهلكون المعالجة. إن لم تخطط لذلك، ستحصل على تحصيل مزدوج، رسائل بريد مزدوجة، وتذاكر دعم غاضبة. الحل ليس غريبًا، لكن يجب أن يكون واعيًا: معالجات قابلة لإعادة التطبيق، معرفات أحداث مستقرة، وقواعد عمل تكشف "تم التطبيق بالفعل".
أخطاء شائعة:
المخططات/versioning تستحق انتباهًا خاصًا. حتى لو بدأت بـ JSON، تحتاج عقدًا واضحًا: الحقول المطلوبة، الحقول الاختيارية، وكيف تنشر التغييرات. تغيير صغير مثل إعادة تسمية حقل يمكن أن يكسر التحليلات أو الفوترة أو تطبيقات الجوال التي تتحدث أبطأ.
فخ آخر هو الإفراط في التفريق. أحيانًا تنشئ الفرق تيارًا جديدًا لكل ميزة. بعد شهر، لا يعرف أحد "ما هي الحالة الحالية للطلب؟" لأن القصة مبعثرة عبر أماكن كثيرة.
لا يلغي تدفق الأحداث الحاجة لنماذج بيانات متينة. لا تزال بحاجة لقاعدة بيانات تمثل الحقيقة الحالية. السجل هو التاريخ، ليس تطبيقك بأكمله.
إذا كنت محتارًا بين طابور وKafka، ابدأ ببعض الفحوص السريعة. ستخبرك إن كنت تحتاج تسليم عمل بسيط بين عمال، أم سجلاً يمكنك إعادة استخدامه لسنوات.
إذا كانت إجاباتك "لا" لإعادة التشغيل، "مستهلك واحد فقط"، و"رسائل قصيرة الأجل"، فالطابور الأساسي عادةً يكفي. إذا كانت إجاباتك "نعم" لإعادة التشغيل، مستهلكون متعددون، أو احتفاظ أطول، فنهج قائم على السجل يدفع قيمته لأنه يحول سيلًا واحدًا من الحقائق إلى مصدر مشترك يمكن للأنظمة الأخرى البناء عليه.
حوّل الإجابات إلى خطة صغيرة قابلة للاختبار.
OrderPlaced, PaymentAuthorized, OrderShipped) ودوّن من ينشر ومن يستهلك كلٍ منها.orderId) ودوّن ماذا يعني "الترتيب الصحيح".إذا كنت تختبر بسرعة، يمكنك رسم تدفق الأحداث في وضع التخطيط في Koder.ai والتكرار على التصميم قبل تثبيت أسماء الأحداث وقواعد الإعادة. بما أن Koder.ai يدعم تصدير الشيفرة، واللقطات، والعودة، فهو طريقة عملية لاختبار شريحة منتج-مستهلك واحدة وضبط أشكال الأحداث دون تحويل التجارب المبكرة إلى دين إنتاجي.
الطابور أفضل لـ تذاكر العمل التي تريد تنفيذها ثم نسيانها (إرسال بريد ترحيبي، تغيير حجم صورة، تشغيل مهمة). السجل أفضل لـ الحقائق التي تريد الاحتفاظ بها والسماح لعدة أنظمة بقراءتها وإعادة تشغيلها لاحقًا (OrderPlaced, PaymentAuthorized, RefundIssued).
ستشعر بالمشكلة عندما يتطلب كل ميزّة جديدة لمس العديد من التكاملات، ويصبح تصحيح الأخطاء سؤالًا عن “من كتب هذه القيمة؟” من دون خط زمني واضح. السجل يساعد لأنّه يصبح سجلًا مشتركًا يمكنك فحصه وإعادة تشغيله بدل التخمين من حالات قواعد بيانات متناثرة.
عندما تحتاج أثر تدقيقي وإمكانية إعادة التشغيل: إصلاح خطأ بإعادة معالجة التاريخ، ملء بيانات ميزة جديدة من سجلات قديمة، التحقيق في “ماذا كنا نعرف حينها؟”، أو دعم مستهلكين متعددين (الفوترة، التحليلات، الدعم، الاحتيال) دون تغيير المنتج في كل مرة.
لأن الأنظمة تفشل بطرق معقّدة: عمليات إعادة المحاولة، انتهاء المهلات، أعطال جزئية، وتصحيحات يدوية. إذا كان كل نظام يحدث الآخرين مباشرةً، فقد يختلف كل منهم حول ما حدث. السجل الإلحاقي يعطيك تسلسلًا مرتبًا واحدًا لتفهمه حتى لو كانت بعض المستهلكات متوقفة ثم التقطت ما فاتتها لاحقًا.
صمّم الأحداث كـ حقائق غير قابلة للتغيير (صيغة الماضي) تصف شيئًا حدث بالفعل:
OrderPlaced، وليس ProcessOrderPaymentAuthorized، وليس ChargeCardNowافترض حدوث تكرارات (التوصيل على الأقل مرة شائع). اجعل كل مستهلك آمنًا لإعادة المحاولة عن طريق:
القاعدة الافتراضية: الصواب أولًا، ثم السرعة.
افضّل التغييرات الإضافية: احتفظ بالحقول القديمة، أضف حقولًا اختيارية جديدة، وتجنّب إعادة التسمية/الحذف الذي يعتمد عليه المستهلكون الحاليون. إذا اضطررت لتغيير متصدع، فعنَوّن الحدث (أو الموضوع/التدفق) وادمج المستهلكين بشكل مدروس بدلاً من تعديل JSON عشوائيًا.
ابدأ بشريحة رقيقة ومتكاملة:
OrderPlaced → إيصال عبر البريد).orderId أو userId).لا. احتفظ بقاعدة بيانات للحالة الحالية والمعاملات (“ما هو الصحيح الآن”). استخدم سجل الأحداث للتاريخ ولإعادة بناء المشاهد المشتقة (جداول التحليلات، فهارس البحث، الجداول الزمنية). التقسيم العملي: قاعدة البيانات للقراءة/الكتابة في المنتج، والسجل للتوزيع، وإعادة التشغيل، والتدقيق.
وضع التخطيط مفيد لرسم الناشرين/المستهلكين، تعريف أسماء الأحداث، وتقرير قواعد الإعادة والاحتفاظ قبل كتابة الكود الإنتاجي. ثم نفّذ شريحة منتج-مستهلك صغيرة، خذ لقطات، وارجع سريعًا أثناء ضبط أشكال الأحداث. بعد الاستقرار يمكنك تصدير الكود ونشره كما أي خدمة أخرى.
UserEmailChangedUpdateEmailإذا تغيّر شيء لاحقًا، انشر حدثًا جديدًا يعلن الحقيقة الجديدة بدلاً من تعديل القديم.
أثبت الحلقة تعمل قبل توسيعها لميزات وفرق أكثر.