المقدمة

المشكلة بدأت لما كنا بنحتاج إننا نعمل processing لعدد كبير من الـ events اللي بنستقبلها من sensors موجودة فى العربيات. بنستخدم ال events دي علشان نحلل سلوك معين للسواقين وكذلك ال rides.

فسيناريو زي ده أول حل ف دماغنا هيجي إننا نستخدم Apache Flink علشان الـ case بتاعتنا streaming و Flink أنسب حد في المهمة دي.

المعروف عن الـ Streaming Engines اللي زي Flink انهم بيستخدموا technique معين علشان يعملوا tracking للـ events خصوصاً الـ event time وواحد من أشهر ال techniques دي هو الـ Watermarks.


فالـ Stream Processing علشان نتأكد إن النتايجة بتاعتنا دقيقة كفاية ، يُفضل إننا نستخدم ال event time مش ال processing time لإن ال event time هو الوقت اللي الـ event فيه generated من الـ source وبالتالي لو حصل أي تأخير لأي سبب في وصول الـ event ده لل engine نقدر نستخدم الـ event time علشان نعرف ال accurate ordering بتاع الـ events اللي جاية وبالتالي نخلي النتايج بتاعتنا أكثر دقة.

الـ Watermarks فـ Flink بتشتغل بإنه بيحصل generation كل وقت معين (default: 200ms) لـ timestamp اسمها الـ Watermark عن طريقها الـ system بيقدر يحدد إنه خلاص انا مش محتاج يستني الـ events المتأخرة لإن كده خلاص عدى وقت كبير وللحفاظ على الـ latency إنها تفضل قليلة (واللي هو من مميزات Flink) الأفضل إننا دلوقتي نبدء processing للـ events الموجودة عندنا.

مشكلة الـ default watermarking mechanism الموجودة فـ Flink إنها بتشتغل على مستوى الـ stream كله ولإن الـ watermark بيحصلها generation بناءً على الـ timestamps بتاعت الـ events اللي بتجيلي ف هنا بتظهر المشكلة.

إنه قيمة الـ watermark بتكبر بسرعة فـ حالة مثلا إنه وصل الـ engines مجموعة من الـ events اللي الـ timestamp بتاعتها عالية واللي في نفس الوقت حصل تأخير لأي سبب لمجموعة تانية من الـ events اللي المفروض انهم كانوا يوصلوا الـ system الأول.

هنا كده حصل مشكلة ترتيب اللي بنقول عليها out-of-orderness.

الحل

كان الحل إننا ليه منعملش watermarking mechanism تكون بتشتغل على كل source من اللي بيبعت الـ events لوحده، بحيث لو في source لسبب ما بيوصل منه الـ events متأخرة ده هيكون له watermark value لوحده ولو في source بيبعت الـ events بسرعة هيكون نفس الكلام له ال watermark value بتاعته وبالتالي مفيش حد هيتأثر بالسلوك بتاع التاني وكل sub-stream هيشتغل لوحده.

وهنا كان بداية شغلنا على extension جديد للـ watermarking component فـ Apache Flink واللي سميناه Keyed Watermarks


Keyed Watermarks

طريقة تنفيذ الفكرة

لحسن حظنا الـ API بتاعت Flink اللي إسمها DataStream API كانت جاهزة وبتوفر لينا حاجات كتير من ضمنها إننا نقدر بسهولة نقسم الـ main stream لـ different sub-stream واللي بيحصل بشكل automatic في Flink عن طريق key الـ application developer هو اللي بيحدده واللي بيكون attribute من ضمن attributes الـ event.

فإحنا بإستخدام الـ key ده نقدر إننا نـgenerate دلوقتي watermark لكل sub-stream وبدأنا نعدل ونـextend الـAPI والـWatermark Generators الموجودة فـ Flink علشان يقبل الـ key كـ parameter جديد وهو بيـ generate الـ watermark.

وعلشان نعمل ده التعديل كان في اماكن كتير في ال watermarking component الموجود في Flink وبدأنا نـfollow الـ watermarking path واللي كان عملية مش سهلة لعدم وجود documentation مناسب وكافي للـ source code بتاع Flink

بعد ما عرفنا إيه الحاجات اللي محتاجة تتغير بدأنا نـdesign الـ component الجديد

التجارب والنتائج

طبعاً إحنا كنا محتاجين نتأكد إن الـ component الجديد شغال صح ف بدأنا نـsimulate stream بإستخدام datasets معينة بـ characteristics معينة قبل وبعد التعديل بحيث نتأكد إنه في حالة إن الـ events بتوصل مترتبة ومفيش أي تأخير إن الـtwo components بتشتغل بنفس الطريقة وبتطلع نفس الـ result لإننا كنا بنقيس metrics جوا ال pipeline واللي إحنا نقدر نتحكم فيها بـ low-level code إحنا كنا بنغير فيه بنفسنا ولما وصلنا أخيراً بعد كذا تجربة إن الـ Keyed Watermarks بتحقق النتائج المطلوبة.

بدأننا إننا نبني environment حقيقية وإستعنا بـ Google Cloud علشان نعمل Cluster حقيقي بإستخدام Docker والـ VMs الجاهزة على Google Cloud وبقى عندنا Flink Cluster جاهز وبدأن فعلاً نعمل run ل experiments حقيقية ب parallelisms مختلفة وعلى أكتر من dataset علشان نتأكد إن كل حاجة شغالة مظبوط والنتائج كانت فعلاً outperforming وقدرنا نقلل الـ data loss في الـ average cases لحد 99% مقارنة بـ data loss كان بيوصل لـ 30% وأكتر.


في الختام

في مساحة كبيرة لتطوير وتحسين الـ stream processing لإنها فعلاً حاجة مهمة جداً في الوقت الحالي، وكان ده بداية الشغل والطريق اللي هنكمل فيه علشان نحسن أكتر.

الـ watermarking اسلوب مهم جداً في الـ streaming engines واللي نقدر من خلاله نحسن أكتر ونخلي الـ pipelines بتاعتنا بتطلع نتائج أحسن من خلال tuning حاجات بسيطة حسب الـ use case.

في تفاصيل كتير لم يتم ذكرها علشان الوقت لكن هتنزل بعد كده في مقالات تانية.