معالجة التدفقات
معالجة التدفقات
كل نظام صممته حتى الآن يعالج البيانات بإحدى طريقتين: إما تخزينها أولاً والاستعلام عنها لاحقاً (المعالجة الدفعية)، أو التصرف بها فور وصولها (معالجة التدفقات). المعالجة الدفعية مباشرة — شغّل استعلام SQL في الساعة الثانية فجراً، أنشئ تقريراً، انتهى. لكن حين يجب معالجة إشارة احتيال خلال 200 مللي ثانية من إجراء المعاملة، أو حين يجب أن تعكس لوحة التحكم آخر 60 ثانية من نشاط المستخدمين، فالمعالجة الدفعية ببساطة أبطأ من أن تُجدي. معالجة التدفقات هي الإجابة.
في جوهرها، معالجة التدفقات تعني التعامل مع البيانات كتدفق لا نهائي ومستمر من الأحداث وحساب النتائج على هذا التدفق في شبه وقت فعلي — دون انتظار انتهاء التدفق (الذي لن ينتهي أبداً). تجري العمليات الحسابية على البيانات في حركتها، لا على البيانات الساكنة.
الدفعي مقابل التدفقي: المقايضة الأساسية
المعالجة الدفعية ومعالجة التدفقات ليستا فلسفتين متنافستين — بل هما أدوات تُختار وفقاً لمتطلبات الكمون. الحد الفاصل تقريباً:
- الدفعية: كمون مقبول يُقاس بالدقائق إلى الساعات. إنتاجية عالية، استعادة بسيطة من الأعطال، سهلة إعادة التشغيل. أمثلة كلاسيكية: خطوط ETL الليلية، دورات الفوترة الشهرية، تدريب نماذج التعلم الآلي دون اتصال.
- التدفقية: كمون مطلوب يُقاس بالمللي ثانية إلى الثواني. إخراج مستمر، استعادة معقدة من الأعطال، أصعب في التصحيح. أمثلة كلاسيكية: كشف الاحتيال، لوحات النتائج الحية، تحديثات التوصيات الفورية، أنظمة التنبيه.
تستخدم كثير من البنيات الحديثة كلتيهما: طبقة التدفق تُغذّي عرضاً فورياً، بينما تُعيد طبقة الدفعات بشكل دوري حساب العرض التاريخي الموثوق. هذه هي الفكرة الجوهرية وراء بنية Lambda (التي تناولناها في الدرس 7).
المفاهيم الأساسية
النوافذ (Windows)
نادراً ما يمكنك حساب نتيجة ذات معنى من حدث واحد معزول. تُطبّق معالجات التدفق نوافذ — شرائح محدودة من التدفق اللانهائي — لتجميع مجموعات من الأحداث:
- النافذة المتدحرجة (Tumbling): فترات ثابتة غير متداخلة. "احسب النقرات كل 60 ثانية." بسيطة، لكن ارتفاعاً مفاجئاً عند حدود نافذتين ينقسم بينهما.
- النافذة المنزلقة (Sliding): نافذة بحجم ثابت تتقدم مع كل حدث. "احسب النقرات في آخر 60 ثانية في أي لحظة." أكثر دقة، وأعلى تكلفة — نوافذ كثيرة تتداخل.
- نافذة الجلسة (Session): تجمع الأحداث بحسب فترة الخمول. "اجمع كل نقرات هذا المستخدم حتى يصبح غير نشط لمدة 30 دقيقة." طبيعية لتحليلات جلسات المستخدم.
الحالة (State)
كثير من عمليات التدفق ذات حالة: العد، المتوسط المتحرك، أو ضم تدفقين يتطلب تذكّر الأحداث السابقة. تُخزّن معالجات التدفق هذه الحالة محلياً (مثل RocksDB داخل كل مهمة Flink) وتُنشئ نقاط تفتيش دورية في التخزين الدائم. عند فشل عقدة، تُستعاد الحالة من آخر نقطة تفتيش ويُستأنف المعالجة من آخر إزاحة Kafka مُلتزم بها — هكذا تتحقق دلالات exactly-once من طرف إلى طرف.
وقت الحدث مقابل وقت المعالجة
للأحداث طابعا زمنيان: وقت الحدث (متى وقع في العالم الحقيقي) ووقت المعالجة (متى استلمه المعالج). تطبيق محمول يعمل دون اتصال لعشر دقائق سيُرسل دفعة من الأحداث المتأخرة حين يعود للاتصال. إن عمّدتَ النافذة بوقت المعالجة، تقع تلك الأحداث في النافذة الخاطئة. التعميد بوقت الحدث أكثر دقة، لكنه يستلزم انتظار العلامات المائية (Watermarks) — إشارة تقول "وصلت الآن كل الأحداث حتى الوقت T". بعد العلامة المائية، تُهمَل الأحداث المتأخرة أو تُشغّل إعادة حساب النافذة.
أبرز أطر معالجة التدفقات
ثلاثة أطر تهيمن على معالجة التدفقات في بيئات الإنتاج اليوم:
- Apache Flink — المعيار الذهبي لمعالجة التدفقات ذات الحالة. دلالات وقت حدث حقيقية، exactly-once من طرف إلى طرف (مع Kafka)، كمون بالمللي ثانية، وواجهة برمجية ثرية للنوافذ والضم. يستخدمه Alibaba (10 مليار حدث يومياً) وNetflix وUber. النموذج الذهني هو رسم بياني موجّه لا دوري (DAG) من المعاملات، كل معامل يدير حالته الخاصة.
- Apache Spark Structured Streaming — امتداد لواجهة Spark الدفعية إلى دفعات مصغّرة من 100 مللي ثانية إلى ثانية واحدة. أسهل في التبني إن كنت تستخدم Spark للمعالجة الدفعية بالفعل. كمون أعلى قليلاً من Flink، لكن الواجهة الموحدة للدفعي والتدفقي تُقلل التعقيد في خطوط بنية Lambda.
- Kafka Streams / ksqlDB — مكتبة خفيفة الوزن (ليست مجموعة منفصلة) تعمل داخل JVMs تطبيقك الخاص، تقرأ من Kafka وتكتب إليه. لا بنية تحتية منفصلة للتشغيل. ممتازة لتحويلات التدفق داخل الخدمة؛ أقل ملاءمة للتجميعات الضخمة عبر الخدمات التي يتعامل معها Flink ببراعة.
مثال حقيقي: كشف الاحتيال على نطاق واسع
معالج الدفعات مثل Stripe يعالج تقريباً 250 مليون معاملة يومياً — نحو 2900 في الثانية عند الحمل المتوسط، مع ذرى أعلى بكثير. كشف الاحتيال بشكل متزامن في مسار الدفع أمر غير قابل للتطبيق: نموذج التسجيل بتعلم الآلة يحتاج سياقاً من آخر 30 معاملة لنفس البطاقة، وآخر 10 دقائق من النشاط على التاجر، وأنماط السرعة التاريخية. جلب كل ذلك بشكل متزامن مع كل معاملة يُدخل كموناً غير مقبول.
بنية معالجة التدفقات بدلاً من ذلك:
- يُنشر حدث كل معاملة إلى Kafka فور الترخيص.
- مهمة Flink تحافظ على حالة مُفهرَسة (keyed state) لكل بطاقة ولكل تاجر — عدادات جارية، نوافذ سرعة، درجات الشذوذ — تُحدَّث مع كل حدث وارد.
- حين يُتجاوز عتبة (مثل 5 معاملات من نفس البطاقة في دقيقتين لتجار مختلفين)، تُصدر Flink إشارة احتيال إلى موضوع Kafka المنبثق في أقل من 50 مللي ثانية.
- خدمة منفصلة تستهلك ذلك الموضوع وتُشغّل تجميداً على البطاقة.
الرؤية الجوهرية: الحالة المكلفة لكل بطاقة يُحافظ عليها باستمرار بواسطة معالج التدفق، لذا تسجيل أي معاملة فردية رخيص — بحث حالة واحد، لا استعلام متعدد الجداول.
دلالات Exactly-Once في التطبيق العملي
تحقيق exactly-once في نظام موزع صعب. ثلاثة ضمانات أضعف أبسط:
- At-most-once: إسقاط الأحداث عند الفشل. الأبسط، لكنك تفقد بيانات.
- At-least-once: إعادة التشغيل عند الفشل. تحصل على تكرارات، يجب على الطرف المستقبل معالجتها (المثالية — تناولناها في الدرس 6).
- Exactly-once: لا فقدان، لا تكرار. يتطلب تنسيق نقاط التفتيش بين المصدر والمعالج والمخرج. تحقق ذلك Flink عبر لقطات Chandy-Lamport الموزعة مقترنةً بمعاملات Kafka. التكلفة: نحو 10–20% من تكاليف الإنتاجية للقطات. تستحق العناء للأنظمة المالية والمخزون.
اختيار الأداة المناسبة
إطار القرار بسيط. اطرح ثلاثة أسئلة:
- ما الكمون الذي تحتاجه؟ أقل من 100 مللي ثانية ← Flink أو Kafka Streams. أقل من ثانية مقبول ← Spark Structured Streaming.
- كم الحالة التي تحملها؟ بلا حالة أو حالة صغيرة ← Kafka Streams يعمل في خدمتك. ضم ثقيل عبر التدفقات وحالة مُفهرَسة ضخمة ← Flink على مجموعة مخصصة.
- هل تستخدم Spark للمعالجة الدفعية بالفعل؟ إن كانت الإجابة نعم، يُقلل Spark Structured Streaming التعقيد التشغيلي بإعادة استخدام نفس المجموعة ونفس المهندسين.
معالجة التدفقات ليست سحراً — إنها تتاجر ببساطة المعالجة الدفعية مقابل قوة الإخراج المستمر ذي الكمون المنخفض. أتقن نموذج النوافذ، افهم دلالات exactly-once، وتعرّف على متطلبات الكمون لديك، وستتمكن من تصميم خطوط أنابيب تحوّل تدفقات الأحداث الخام إلى ذكاء أعمال في الوقت الفعلي.