Skip to content

طوابير المهام غير المتزامنة ونموذج المنتج-المستهلك

مقدمة

المستخدم ينقر على زر "تصدير التقرير"، ثم يحدق في أيقونة التحميل الدوارة لمدة 30 ثانية - هل هذا معقول؟ عندما تستغرق عملية ما عدة ثوانٍ أو حتى دقائق، فإن جعل المستخدم ينتظر ليس تجربة جيدة بوضوح. طابور المهام غير المتزامنة هو النمط المعماري الأساسي لحل هذه المشكلة - رمي العمليات المستهلكة للوقت إلى الخلفية للمعالجة، والسماح للمستخدم بالحصول على استجابة فورية.

ماذا ستتعلم في هذا المقال؟

بعد إكمال هذا الفصل، ستكتسب:

  • مقارنة المتزامن وغير المتزامن: فهم لماذا يجب جعل بعض العمليات غير متزامنة، وتحسين تجربة المستخدم الناتج عن ذلك
  • نموذج المنتج-المستهلك: إتقان الفكرة الأساسية لنمط Producer-Consumer وسير العمل
  • آلية تجمع Worker: فهم كيفية توزيع المهام على عدة Workers للمعالجة المتوازية
  • ضمان الموثوقية: إتقان آليات الضمان مثل إعادة محاولة المهام واللامتغيرية وطابور الرسائل الميتة
  • قدرة اختيار التقنية: فهم خصائص أطر المهام غير المتزامنة الرئيسية وسيناريوهاتها المناسبة
الفصلالمحتوىالمفاهيم الأساسية
الفصل 1لماذا نحتاج غير المتزامنالحظر المتزامن مقابل غير المتزامن غير الحاظر
الفصل 2نموذج المنتج-المستهلكProducer، Queue، Consumer
الفصل 3تجمع Workerالمعالجة المتوازية، توزيع المهام
الفصل 4ضمان الموثوقيةاستراتيجية إعادة المحاولة، اللامتغيرية، طابور الرسائل الميتة
الفصل 5اختيار الإطارCelery، Sidekiq، Bull، RQ

0. النظرة الشاملة: لماذا لا يمكن جعل المستخدم "ينتظر"؟

تخيل أنك تذهب إلى مطعم لتطلب طعامًا. المطعم الجيد سيعطيك رقم طلب فورًا بعد طلبك، ثم يمكنك الجلوس واللعب بهاتفك، وتأتي لاستلامه عندما يكون جاهزًا. بدلاً من أن تقف عند المنضدة وتحدق في الطاهي وهو يعد الطبق كاملاً.

هناك العديد من عمليات "إعداد الطعام" المشابهة في تطبيقات الويب:

  • إرسال البريد الإلكتروني/الرسائل النصية: استدعاء API خارجي، قد يستغرق عدة ثوانٍ
  • إنشاء التقارير/PDF: حسابات بيانات كبيرة، قد تستغرق عشرات الثواني
  • معالجة الصور/الفيديو: ضغط، تحويل الترميز، إضافة علامة مائية، قد تستغرق دقائق
  • مزامنة البيانات: مزامنة بيانات عبر الأنظمة، الوقت غير محدد

الفكرة الأساسية للمهام غير المتزامنة

فصل العمليات المستهلكة للوقت من التدفق الرئيسي "طلب-استجابة"، ووضعها في طابور خلفي للمعالجة غير المتزامنة. يحصل المستخدم على استجابة "تم الاستلام، قيد المعالجة" فورًا بعد تقديم الطلب، وعند اكتمال المعالجة يتم إبلاغه بالنتيجة عبر الإشعارات أو الاستطلاع أو WebSocket.


1. المتزامن مقابل غير المتزامن: قصة طلب

عندما يقدم المستخدم طلبًا، تحتاج الخلفية إلى القيام بأشياء كثيرة: خصم المخزون، إنشاء سجل الطلب، إرسال بريد تأكيد، تحديث نظام التوصيات، تسجيل سجل التدقيق...

في الوضع المتزامن، تنفذ هذه العمليات تسلسليًا، ويجب على المستخدم انتظار اكتمال جميع العمليات لرؤية النتيجة. في الوضع غير المتزامن، تحتاج فقط لإكمال العمليات الأساسية (خصم المخزون، إنشاء الطلب)، وباقي العمليات تُرمى في الطابور للمعالجة الخلفية.

Synchronous vs Asynchronous Processing
Click the button to compare the two processing modes
User request
Waiting to submit
Server processing
Reserve inventory50ms
Create order100ms
Send confirmation email800ms
Update recommendation system600ms
Write audit log300ms
بعد المقارنةالمعالجة المتزامنةالمعالجة غير المتزامنة
وقت انتظار المستخدمإجمالي وقت جميع العملياتوقت العمليات الأساسية فقط
إنتاجية النظاممنخفضة (الخيط محظور)عالية (تحرير سريع للخيط)
تأثير الفشلفشل غير الأساسي يؤدي لفشل كليفشل غير الأساسي لا يؤثر على التدفق الرئيسي
تعقيد التنفيذبسيطيحتاج بنية تحتية إضافية للطابور
اتساق البياناتاتساق قوياتساق نهائي

متى نستخدم غير المتزامن؟

ثلاثة معايير للحكم: مستهلك للوقت (أكثر من 1-2 ثانية)، غير أساسي (الفشل لا ينبغي أن يؤثر على التدفق الرئيسي)، قابل للتأخير (لا حاجة للنتيجة فورًا). إذا تحقق أي اثنين منها، يجب النظر في جعلها غير متزامنة.


2. نموذج المنتج-المستهلك: "خط تجميع" المهام

جوهر طابور المهام غير المتزامنة هو نمط المنتج-المستهلك (Producer-Consumer Pattern) الكلاسيكي. هذا النمط له ثلاثة أدوار:

  • المنتج (Producer): الطرف الذي ينتج المهام، عادةً خادم الويب عند معالجة طلبات المستخدم
  • الطابور (Queue): المخزن المؤقت لتخزين المهام المعلقة، عادةً باستخدام Redis أو RabbitMQ إلخ
  • المستهلك (Consumer/Worker): عملية العمل التي تسحب المهام من الطابور وتنفذها
Worker Pool Model
Watch tasks get distributed to different workers
Worker count: 3
Task queue (0)
Queue is empty
Workers
Worker 1
💤 Idle
Completed: 0
Worker 2
💤 Idle
Completed: 0
Worker 3
💤 Idle
Completed: 0
Completed (0)
None yet

القيم الثلاث للطابور

  1. فك الارتباط: المنتج لا يحتاج لمعرفة من سيعالج المهمة، والمستهلك لا يحتاج لمعرفة من أين أتت المهمة
  2. تنعيم الذروة: عند التدفق المفاجئ، تتراكم المهام في الطابور أولاً، ويعالجها المستهلك بإيقاعه الخاص
  3. الموثوقية: المهام مخزنة بشكل دائم في الطابور، حتى لو تعطل المستهلك لن تضيع
المكونالمسؤوليةالتنفيذ الشائع
وسيط الرسائلتخزين وإعادة توجيه رسائل المهامRedis، RabbitMQ، Kafka
المتسلسلتسلسل/إلغاء تسلسل معاملات المهمةJSON، MessagePack، Pickle
المجدولإدارة المهام المجدولة والمؤجلةCron، APScheduler، node-cron
مخزن النتائجحفظ نتائج تنفيذ المهمةRedis، قاعدة البيانات، S3

3. ضمان الموثوقية: المهمة لا يجب أن "تضيع" ولا أن "تتكرر"

في البيئة الموزعة، قد تحدث مشاكل مثل تقلب الشبكة وإعادة تشغيل الخدمات ونقص الموارد في أي وقت. يجب أن يمتلك نظام المهام غير المتزامنة آليات ضمان موثوقية كاملة.

المشكلتان الأساسيتان: فقدان المهمة (المستهلك يتعطل في منتصف المعالجة) والتنفيذ المتكرر (تم تسليم المهمة مرتين).

Task Retry and Backoff Strategies
Simulate the retry process after a task fails
Fixed interval
Every retry waits for the same duration. It is simple, but can cause retry storms.
Delay formula:delay = 2s

ثلاث أدوات الموثوقية

  1. آلية ACK: يرسل المستهلك تأكيدًا (ACK) فقط بعد اكتمال معالجة المهمة، والمهام غير المؤكدة يعاد تسليمها
  2. استراتيجية إعادة المحاولة: إعادة المحاولة حسب الاستراتيجية عند فشل المهمة، التراجع الأسي + التشويش هو أفضل ممارسة
  3. تصميم اللامتغيرية: تنفيذ نفس المهمة عدة مرات له نفس تأثير التنفيذ مرة واحدة، يتحقق من خلال إزالة التكرار بمعرف فريد
الآليةالمشكلة التي تحلهاطريقة التنفيذ
تأكيد ACKفقدان المهمةتأكيد يدوي بعد اكتمال المعالجة، إعادة التسليم عند انتهاء المهلة دون تأكيد
طابور الرسائل الميتة (DLQ)"الرسائل السامة" التي تفشل مرارًابعد تجاوز حد إعادة المحاولة، تنقل إلى طابور الرسائل الميتة، للمعالجة اليدوية
اللامتغيريةالتنفيذ المتكررإزالة التكرار بمعرف فريد للمهمة، قيد فريد في قاعدة البيانات
طابور الأولويةتجويع المهمةالمهام عالية الأولوية تعالج أولاً، لتجنب الحظر بالمهام منخفضة الأولوية
التحكم في المهلةتجمد المهمةتعيين وقت أقصى للتنفيذ، إنهاء تلقائي وإعادة محاولة عند تجاوز المهلة

4. اختيار الإطار: اختر الأداة المناسبة لك

الأنظمة البيئية للغات المختلفة لها أطر مهام غير متزامنة مختلفة، تختلف في ثراء الوظائف والأداء وسهولة الاستخدام. عند اختيار إطار، فكر أولاً في مجموعتك التقنية، ثم قرر حسب حجم المشروع ومتطلباته.

Popular Async Task Frameworks
Click a framework to inspect the details
Celery
Python
Sidekiq
Ruby
Bull
Node.js
RQ
Python
Kafka Streams
Java/JVM
CeleryPython
The most popular distributed task queue in the Python ecosystem. It supports multiple brokers such as RabbitMQ and Redis, with a broad feature set and active community.
Core features:
Scheduled tasksTask chainsResult backendAutomatic retriesPriority queuesTask routing
Typical scenarios:
Data pipelines, email sending, report generation, machine learning training jobs

نصائح الاختيار

  • مشاريع Python: المتوسطة والكبيرة تستخدم Celery، الصغيرة تستخدم RQ
  • مشاريع Node.js: الخيار الأول BullMQ (الجيل التالي من Bull)
  • مشاريع Ruby: Sidekiq هو الخيار الوحيد تقريبًا
  • مشاريع Java: نظام Spring يستخدم Spring Batch، الإنتاجية العالية تستخدم Kafka Streams
  • مشاريع Go: Asynq (مبني على Redis) أو Machinery

إذا كان مشروعك يستخدم Redis بالفعل، فإن الحلول المبنية على Redis (Celery+Redis، BullMQ، Sidekiq) هي أبسط طريقة للبدء.


الخلاصة

طابور المهام غير المتزامنة هو بنية تحتية لا غنى عنها في معمارية الخلفية. إنه يمكّن النظام من التعامل بأناقة مع العمليات المستهلكة للوقت، ويحسن تجربة المستخدم مع زيادة إنتاجية النظام.

مراجعة النقاط الرئيسية لهذا الفصل:

  1. معايير الحكم على جعلها غير متزامنة: مستهلكة للوقت، غير أساسية، قابلة للتأخير - إذا تحقق اثنان يجب جعلها غير متزامنة
  2. نموذج المنتج-المستهلك: Producer → Queue → Consumer، الثلاثة متعاونون بفك ارتباط
  3. تجمع Worker: عدة Workers تستهلك بالتوازي، لزيادة قدرة المعالجة
  4. ضمان الموثوقية: تأكيد ACK + استراتيجية إعادة المحاولة + اللامتغيرية، الثلاثة لا غنى عن أي منها
  5. اختيار الإطار: اختر حسب المجموعة التقنية وحجم المشروع، Redis هو أشهر وسيط رسائل

قراءة إضافية