ضمانات التسليم: مرة واحدة كحد أقصى، ومرة واحدة على الأقل، ومرة واحدة بالضبط
ضمانات التسليم: مرة واحدة كحد أقصى، ومرة واحدة على الأقل، ومرة واحدة بالضبط
كل نظام مراسلة موزّع يجب أن يجيب عن سؤال جوهري واحد: حين يُرسل المُنتِج رسالةً، كم مرةً سيستقبلها المُستهلك ويعالجها؟ الإجابة ليست "مرةً واحدةً بالضبط" بصفة افتراضية تقريباً في أي وقت — بل تعتمد على طيف من الضمانات، لكلٍّ منها مُقايضاته الملموسة من حيث زمن الاستجابة والإنتاجية والتعقيد والصحة. الخطأ هنا قد يعني ضياع معاملات مالية، أو إرسال تأكيدات طلبات مكرّرة، أو بيانات تحليلية تالفة.
ثمة ثلاثة دلالات قياسية للتسليم. فهمها — ومعرفة أيّها تحتاج فعلاً — هو أحد أهم القرارات في تصميم الأنظمة غير المتزامنة.
التسليم مرة واحدة كحد أقصى (At-Most-Once)
يُطلق الوسيط الرسالةَ وينسى أمرها. تُسلَّم الرسالة صفراً أو مرةً واحدة — لن تُسلَّم مرتين أبداً، لكنها قد تضيع كلياً. يُرسل المُنتِج الرسالة دون انتظار تأكيد، ويتخلى الوسيط عنها فور محاولة التسليم الأولى بصرف النظر عن نجاح المُستهلك.
أين يظهر: قياسات الأداء عبر UDP، شحن السجلات دون انتظار استجابة، مقاييس الوقت الفعلي (حين يُقبل فقدان نقطة بيانات واحدة)، قراءات أجهزة استشعار إنترنت الأشياء حيث البيانات القديمة عديمة القيمة.
المقايضات: أدنى زمن استجابة، أعلى إنتاجية، وصفر تكلفة لإزالة التكرار. لكن فقدان البيانات احتمال حقيقي عند أي اضطراب شبكي أو عطل في المُستهلك. استخدم هذا الأسلوب فقط حين يكون فقدان الرسائل أرخص من تكلفة الموثوقية.
مثال واقعي: خط أنابيب تحليلات لعبة يُصدر 500,000 حدث في الثانية لبيانات سلوك اللاعبين. فقدان 0.1% من تلك الأحداث في حالة ازدحام شبكي له تأثير ضئيل على التقارير التجميعية. تكلفة التأكيد وإعادة المحاولة ستُخفّض الإنتاجية إلى النصف دون فائدة عملية.
التسليم مرة واحدة على الأقل (At-Least-Once)
يُعيد الوسيط المحاولة حتى يتلقى تأكيداً. تُسلَّم الرسالة مرةً أو أكثر — لا تضيع بيانات، لكن التكرار ممكن. يجب على المُستهلك أن يُقرّ (ACK) كل رسالة صراحةً. إن لم يتلقَّ الوسيط تأكيداً خلال مهلة زمنية، يُعيد وضع الرسالة في قائمة الانتظار ويُسلّمها مجدداً.
أين يظهر: RabbitMQ مع تفعيل ack، وKafka مع acks=all وعدم الالتزام بإزاحة المُستهلك إلا بعد اكتمال المعالجة، وقوائع انتظار SQS القياسية، ومعظم قوائع مهام الشركات.
المقايضات: ضمان متانة قوي — تصمد الرسائل أمام أعطال الوسيط والمُستهلك. لكن التكرار حتمي: قد تتسبب مهل الشبكة في إعادة التسليم حتى بعد أن يكون المُستهلك قد عالج الرسالة بنجاح (وعطل قبل إرسال التأكيد). يجب أن يكون منطق مُستهلكك مُتكافئاً (idempotent) (يُغطى في الدرس 6).
مثال واقعي: خدمة معالجة طلبات. إن تعطّل المُستهلك بعد خصم بطاقة الائتمان لكن قبل إرسال التأكيد، يُعيد الوسيط التسليم. على المُستهلك اكتشاف التكرار (مثلاً بالتحقق مما إذا كان الطلب بذلك المعرّف موجوداً بالفعل) بدلاً من خصم البطاقة مرة ثانية.
التسليم مرة واحدة بالضبط (Exactly-Once)
الهدف المنشود: تُسلَّم الرسالة وتُعالَج مرةً واحدةً بالضبط، بصرف النظر عن إعادات المحاولة والأعطال وإخفاقات الشبكة. لا تضيع بيانات ولا تظهر تكرارات. في الممارسة العملية يُنفَّذ هذا عبر مزيج من المُنتِجين المتكافئين وإزالة التكرار على مستوى الوسيط والمُستهلكين الترانزاكشينيين.
كيف يُنفّذه Kafka: تستخدم دلالات exactly-once في Kafka ثلاث آليات معاً:
- المُنتِج المتكافئ — كل رسالة تحصل على رقم تسلسلي؛ يُزيل الوسيط التكرار في الرسائل المُعاد إرسالها ضمن جلسة واحدة.
- المعاملات (Transactions) — يمكن للمُنتِج الكتابة ذرياً إلى تقسيمات متعددة؛ إما تُكتب جميع البيانات أو لا تُكتب أيّها.
- ذرية القراءة-المعالجة-الكتابة — يُلتزم المُستهلك بإزاحته والمخرجات المعالجة في معاملة ذرية واحدة، فيترك أي عطل أثناء المعالجة النظامَ في حالة متسقة.
المقايضات: التسليم مرة بالضبط أبطأ بنسبة 20-30% من "مرة على الأقل" في معايير Kafka بسبب عبء الالتزام ثنائي المرحلة. يتطلب أيضاً مشاركة خط الأنابيب بأكمله — فإن كتب المُستهلك إلى قاعدة بيانات خارجية لا تدعم المعاملات الموزّعة، يصبح التسليم الحقيقي مرة بالضبط مستحيلاً عند تلك الحدود.
مثال واقعي: دفتر أستاذ مالي يستهلك من Kafka. كل حدث يمثّل خصماً أو إيداعاً. تسليمه مرتين سيُفسد أرصدة الحسابات؛ فقدانه سيُسبّب تفاوتات غير مُفسَّرة. Kafka EOS مع قاعدة بيانات ترانزاكشينية (PostgreSQL) هو الحل الصحيح.
كيف تُولِّد الأعطال التكرار — فجوة التأكيد (ACK Gap)
السبب الأكثر شيوعاً للتكرار في دلالات "مرة على الأقل" هو فجوة التأكيد: النافذة الزمنية بين انتهاء المُستهلك من المعالجة وإرساله التأكيد للوسيط.
هذه الفجوة لا يمكن تجنّبها في الأنظمة الموزّعة. الحل ليس القضاء على الفجوة بل جعل مُستهلكك متكافئاً (idempotent) — مُصمَّماً بحيث معالجة الرسالة ذاتها مرتين له الأثر ذاته لمعالجتها مرةً واحدة. التكافؤ يُعالَج بعمق في الدرس 6.
اختيار الضمان المناسب
اختَر بناءً على ما يتحمّله عملك التجاري:
- At-most-once — استخدمه حين يكون فقدان الرسائل مقبولاً وتكون الإنتاجية أو زمن الاستجابة هو الأولوية. المقاييس، والبيانات التحليلية، والتوصيات الآنية، ونتائج المباريات المباشرة.
- At-least-once — استخدمه حين لا يمكنك فقدان البيانات ويمكنك جعل مُستهلكك متكافئاً. هذا الافتراضي الصحيح لمعظم أنظمة الإنتاج: معالجة الطلبات، وإرسال البريد الإلكتروني، وتحديثات المخزون.
- Exactly-once — استخدمه فقط حين الفقدان والتكرار كلاهما غير مقبولَين وخط الأنابيب بأكمله يدعمه. دفاتر الأستاذ المالية وأنظمة الفوترة وسجلات التدقيق حيث يكون التكافؤ على مستوى التطبيق أمراً غير عملي.
مرجع سريع
| الدلالة | فقدان بيانات؟ | تكرار؟ | التعقيد | متى تستخدم |
|---|---|---|---|---|
| At-most-once | ممكن | أبداً | منخفض | المقاييس، البيانات التحليلية |
| At-least-once | أبداً | ممكن | متوسط | الطلبات، البريد (متكافئ) |
| Exactly-once | أبداً | أبداً | مرتفع | دفاتر مالية، الفوترة |