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

ما هي قائمة انتظار الرسائل الثابتة الموزعة؟
تعرّف ويكيبيديا
قائمة انتظار الرسائل بأنها "مكون هندسة البرمجيات المستخدم للتفاعل المتبادل أو التفاعل المتداخل ضمن عملية واحدة". في الواقع ، هذا المفهوم أوسع إلى حد ما: يمكن أن تقع العمليات التي تتفاعل باستخدام قائمة انتظار على خوادم مختلفة وحتى في مراكز بيانات مختلفة.
سنقوم بتوضيح الشروط قليلا.
قائمة انتظار الرسائل هي مستودع يوفر تحديد موضع وقراءة البيانات بترتيب معين.
عادةً ما يتفاعل نوعان من الكيانات مع قائمة انتظار:
- الكتاب (المنتجين) - إرسال رسائل إلى قائمة الانتظار ؛
- القراء (المستهلكون) - تلقي (قراءة) الرسائل من قائمة الانتظار.
عند استخدام قائمة الانتظار ، يكون القراء والكتاب مستقلين عن بعضهم البعض. يمكنهم العمل بأداء وموثوقية وتوافر مختلفين ويمكن حتى كتابتهم بلغات برمجة مختلفة.
السيناريو الرئيسي لقائمة الانتظار: يمكن بث الرسائل بسرعة وبسرعة من الكاتب إلى القارئ. بخلاف قاعدة البيانات ، قائمة الانتظار غير مخصصة لتخزين الرسائل على المدى الطويل. في العديد من التطبيقات الشائعة ، هناك معلمة مقابلة - "فترة الاحتفاظ بالرسائل". وهي تحدد مدة تخزين الرسالة حتى يتم حذفها نهائيًا.
اكتشفنا مفهوم قائمة الانتظار ، انتقل إلى "التوزيع" و "الثبات".
- التوزيع في حالتنا يعني وجود مجموعة تقوم بتخزين ومعالجة البيانات وبيانات تعريف قائمة الانتظار ، وتجمع كل العقد في مجموعة واحدة باستخدام شبكة الكمبيوتر.
- يعني الثبات أن جميع الرسائل في قائمة الانتظار تتم كتابتها على القرص ، ويتلقى الكاتب تأكيدًا على الإرسال فقط بعد التسجيل الناجح.
لا يؤثر التوزيع والثبات على الوظيفة الرئيسية لقائمة الانتظار ، فهي توفر التسامح مع الخطأ وموثوقية تخزين البيانات. ما أنواع الإخفاقات التي يمكن أن تحدث في نظامنا ، سننظر لاحقًا. ومع ذلك ، لا يمكنني حرمان نفسي من السعادة وفتح البطاقات قليلاً: في تاريخ وجود الخدمة بالكامل ، لم نفقد رسالة عميل محفوظة واحدة.
ما هي قائمة انتظار الرسائل؟
تسمح لك قائمة الانتظار بفصل الأجزاء المستقلة منطقياً عن الخدمات عن بعضها البعض ، أي أنها توفر
فك الارتباط ، وهو أمر مطلوب بشدة في الخدمات الميكروية الشائعة الآن. يؤدي ذلك إلى زيادة قابلية التوسع والموثوقية: يمكنك دائمًا زيادة تدفق التسجيلات في قائمة الانتظار وإضافة المزيد من القراء - معالجات الرسائل ، في حين أن فشل القراء لا يؤثر على عمل الكتاب.
قوائم الانتظار تهدئة أحمال الذروة: فهي بمثابة مخازن مؤقتة للقراء. إذا لم تكن سعة القارئ الحالية كافية للمعالجة الفورية لجميع الرسائل الواردة ، فستتم معالجة الرسائل في قائمة الانتظار لاحقًا عند انخفاض التحميل. التخزين المؤقت مفيد للخدمات ذات التحميل غير المستقر ، حيث لا تكون هناك حاجة إلى الأحداث الواردة الفورية.
دعونا نرى كيف يعمل ، وذلك باستخدام مثال
الروبوت البحث (بعد كل شيء ، بدأت ياندكس مع البحث!) ، والذي ينزل ، ويعالج ويضع صفحات الويب في قاعدة بيانات. لنأخذ مثل هذه الهندسة المعمارية.
قائمة انتظار الرسائل يحل المشاكل التالية هنا:
- يعمل الروبوت بشكل أسرع بكثير من العمال المسؤولين عن تحليل الصفحات وتحميلها في قاعدة البيانات. خارج الخط ، فإن الروابط تتراكم وتملأ الذاكرة أو القرص المتاح. سيحدث نفس الشيء إذا كان العمال غير متاحين مؤقتًا.
- بدون طابور ، يحتاج الروبوت إلى "معرفة" واجهة عمل العمال من أجل إسناد المهام إليهم. قد تتغير الواجهة مع تطور المنتج.
- يتمتع العامل الفرد بموثوقية منخفضة إلى حد ما ، لذلك لا يوجد ضمان بأن تتم معالجة الرابط المنقول بواسطته تمامًا.
توفر قائمة الانتظار تخزينًا موثوقًا للبيانات مع القياس ، مما يسمح لك بتأخير معالجة الارتباطات. إذا فشل عامل ، فسيتم إرجاع الرابط الخام بعد فترة زمنية محددة إلى قائمة الانتظار للمعالجة من قبل عامل آخر. قائمة الانتظار لها واجهة خاصة بها ، والتي يتم اختبارها ووصفها في الوثائق ، بحيث يمكن للبحث عن الروبوت وأنظمة العامل تطوير فرق مختلفة بلغات البرمجة المختلفة. هذا لن يؤثر على الأداء العام.
كيف يعمل Yandex Message Queue مع الرسائل
يمكن تمييز ثلاث مراحل رئيسية هنا:
- كتابة رسالة إلى قائمة الانتظار ؛
- قراءة رسالة من قائمة الانتظار ؛
- إزالة رسالة من قائمة الانتظار.
يعتبر السجل ناجحًا إذا تم تخزين الرسالة بشكل آمن وستتاح قريبًا للقراء. من الممكن تسجيل إلغاء البيانات المكررة: عندما يتم تجاهل محاولة متكررة لتسجيل رسالة مرسلة.
في وقت قراءة الرسالة ، تكون الرسالة مخفية عن قائمة الانتظار لفترة من الوقت تسمى زمن الرؤية ، وتصبح غير قابلة للوصول إلى القراء الآخرين. في حالة انتهاء مهلة الرؤية ، تعود الرسالة إلى قائمة الانتظار وتصبح متاحة للمعالجة مرة أخرى. يتم تحديد ترتيب قراءة الرسائل حسب قائمة الانتظار ، وليس بواسطة القارئ.
القارئ نفسه واتصال الشبكة به غير موثوق بها. تعد مهلة الرؤية ضرورية لتتمكن من إرجاع رسالة إلى قائمة الانتظار عند تعطل القارئ أو قطع الاتصال. خلاف ذلك ، فمن المحتمل أن رسالة واحدة لن تتم معالجتها بشكل صحيح.
بعد القراءة الناجحة ، يتم إرسال الرسالة إلى العميل باستخدام المعرف ReceiptHandle. يشير المعرف إلى بيانات محددة يجب إزالتها من قائمة انتظار الرسائل.
أنواع قوائم الانتظار في قائمة انتظار الرسائل في ياندكس
النوع الأول والأكثر استخدامًا هو قائمة الانتظار القياسية. تتميز بإنتاجية عالية (آلاف الرسائل في الثانية) ، والأداء الممتاز ووقت التنفيذ القصير للعمليات الأساسية. تتكون قوائم الانتظار القياسية من القطع المنطقية وتدعم تقريب عرض النطاق الترددي الخطي تقريبًا.
لا تدعم قوائم الانتظار القياسية إلغاء البيانات المكررة للرسالة عند الكتابة إلى قائمة انتظار ولا تضمن ترتيب القراءة. بسبب استخدام المشاركة ، قد لا يُرجع طلب القراءة رسالة واحدة ، حتى إذا كانت في قائمة الانتظار. يحدث هذا غالبًا في وضع
الاقتراع القصير ، عندما تأتي القراءة من قشرة مختارة بشكل عشوائي.
النوع الثاني -
FIFO - هو عكس قائمة الانتظار القياسية. يوفر ترتيبًا صارمًا للقراءة ، ويدعم إلغاء البيانات المكررة عند الكتابة والمحاولات المتكررة لقراءة الرسائل. الأداء وقابلية التوسع أقل من المعيار. يقتصر أداء قائمة انتظار FIFO على 30 طلبًا في الثانية. يوصى باستخدام FIFO عندما تحتاج إلى محاولة التأكد من دلالات التسليم "مرة واحدة بالضبط". عادةً ما تعني كلمة "قائمة الانتظار" FIFO.
Yandex Message Queue API
API هي عنصر مهم للغاية في أي منتج. يجب أن تكون واجهة البرنامج الجيدة بسيطة ومباشرة ، وتتطلب الحد الأدنى من الإلمام بالوثائق للاستخدام الفعال. يجب ألا تسمح بالقيام بأعمال غريبة أو غير ضرورية وحماية من الأخطاء الغبية ، والإبلاغ في الوقت المناسب عن انتهاك "العقد".
إذا كان لدى النظام واجهة برمجة تطبيقات من هذا القبيل ، فإنه يستقبل المستخدمين المخلصين بسرعة ويحيط به "غلافات" ملائمة لمختلف المنصات ولغات البرمجة.
واجهة برمجة تطبيقات Amazon Simple Queue Service (AWS SQS API) هي مثال على هذه الواجهة التي تم اختبارها حسب الوقت وعدد كبير من العملاء. لذلك ، قررنا عدم اختراع واجهة فريدة لـ Yandex Message Queue ، لكننا نفّذنا الدعم لـ AWS SQS API وبحرص شديد.
في معظم الحالات ، يكفي للمستخدم SQS تغيير نقطة النهاية (عنوان الخدمة) ، والمنطقة (في الوقت الحالي نستخدم فقط "ru-central1") والحصول على بيانات اعتماد جديدة داخل Yandex.Cloud. كل شيء آخر ، على سبيل المثال ، البرنامج النصي الذي يستخدم
سطر أوامر AWS أو الكود باستخدام AWS SDK أو خدمة جاهزة على
Celery أو
boto ، على الأرجح ، لن يكون بحاجة إلى لمسه. سيبقى منطق وظيفة قائمة الانتظار كما هي.
يوجد وصف تفصيلي لأساليب Yandex API Queue API في
وثائق الخدمة .
قليلا عن الراحة
Yandex Message Queue هي خدمة مُدارة ، أي Yandex. Cloud هي المسؤولة عن تشغيل الخوادم والبرامج. يراقب فريق الخدمة صحة قوائم الانتظار ، ويستبدل بسرعة الأقراص الفاشلة ، ويزيل انقطاع الشبكة ويعرض التحديثات. لا يؤدي التحديث إلى إيقاف الخدمة: بينما نقوم بتثبيت الإصدار الجديد من YMQ على مجموعة واحدة من الخوادم ، يعيد موازن التحميل توجيه حركة المرور إلى الآخرين بعناية. لذلك لا يلاحظ المستخدمون أي شيء.
لجعله أكثر ملاءمة لك للتحكم في تشغيل قوائم الانتظار ، قمنا بإضافة عدد كبير من الرسوم البيانية البصرية إلى YMQ ، يتم عرض جزء صغير منها فقط هنا. توجد المخططات في وحدة تحكم Yandex.Cloud ، في قسم "الإحصائيات".
سنخبرك عن الرسوم البيانية الأربعة الأكثر فائدة في رأينا:
- يساعدك الرسم البياني "رسائل قائمة الانتظار" في مراقبة تراكم البيانات في قائمة الانتظار. قد يعني النمو في الرسم البياني أن معالجات لا يديرون الحمل أو توقف المعالجة.
- الرسم البياني "عمر أقدم رسالة في قائمة الانتظار" : تشير القيم الكبيرة إلى مشاكل في معالجة الرسالة. إذا كان كل شيء يعمل بشكل صحيح ، فلا ينبغي أن تكون الرسائل في قائمة الانتظار لفترة طويلة.
- يظهر الرسم البياني "عدد محاولات قراءة رسالة" عندما تبدأ الرسائل في القراءة عدة مرات. هذا قد يعني أن معالجات تعطل عندما يتلقون بعض الرسائل.
- يوضح الرسم البياني "وقت الانتظار" مقدار الوقت المنقضي من لحظة إرسال الرسالة إلى قائمة الانتظار حتى يتلقى المعالج ذلك.
تساعد الرسوم البيانية في تقييم ديناميكيات قائمة الانتظار ووجود حالات الفشل على الفور دون الحاجة إلى عرض السجلات.
ناقشنا أكثر أو أقل من النقاط العامة ، والآن دعنا ننتقل إلى التفاصيل.
كيف تستخدم قاعدة بيانات Yandex Queue قاعدة بيانات Yandex
خدمة Yandex Message Queue مبنية على قمة
قاعدة بيانات Yandex Database (YDB) الموزعة جغرافياً والتي توفر تناسق ودعم صارمين لمعاملات ACID. لن نقوم الآن بتفكيك جهازها وخصائصها ، وسنقتصر على المخطط العام.
تتكون قائمة الانتظار في YMQ من القطع المنطقية ، ممثلة في مجموعة ثابتة من جداول YDB. يخزن كل جدول قطعة المعلومات الخاصة به. على سبيل المثال ، هناك جدول حالة عام يسمى الحالة ، والذي يخزن الإزاحات والعدد الفعلي للرسائل. هناك جدول مع البيانات والبيانات الوصفية للرسالة. هناك جدول مع السمات ذات الصلة.
جميع العمليات الرئيسية مع قائمة الانتظار - العمل مع الرسائل ، وتغيير السمات ، وإنشاء وحذف - وهذا يعمل مع التسلسل الهرمي للجداول وأدلة YDB ، أو استعلامات المعاملات إلى جدول واحد أو أكثر من قائمة الانتظار. البيانات داخل جداول قائمة الانتظار هي مصدر الحقيقة المطلقة. لذلك ، بالإضافة إلى التشغيل الصحيح والمستقر لقاعدة البيانات ، من الضروري ضمان تخزين موثوق ومدى توافر البيانات بشكل كبير.
يتم تخزين معلوماتنا في عدة نسخ متماثلة: نسخة واحدة في كل من مراكز بيانات ياندكس الثلاثة. في حالة عدم توفر أحد مراكز البيانات ، يتضاعف عدد النسخ المتماثلة في المراكز المتبقية. وبالتالي ، يتم استعادة المستوى المطلوب من الموثوقية. حتى في حالة فشل مركز بيانات بأكمله ومكتب خدمة واحد في آخر ، ستكون البيانات قابلة للوصول بالكامل.
الإصدار الأول من بنية قائمة انتظار الرسائل في ياندكس
بدا الإصدار الأول من بنية YMQ ، الذي أطلقنا عليه نحن السذاجة ، هكذا.
يُظهر الرسم التخطيطي مسار طلب HTTPS من عميل YMQ إلى مستودع YDB. لنلق نظرة على المكونات الرئيسية:
- يرسل L3-balancer طلبًا إلى مركز بيانات Yandex الأقرب إلى المستخدم. هذا يقلل من زمن الوصول إلى الشبكة ، على الرغم من أن الحمل يتم توزيعه بشكل غير متساو.
- يقوم Nginx على الجهاز الظاهري Yandex.Cloud بإنهاء اتصالات HTTPS ، ويوفر الحماية من هجمات الشبكة ، ويقوم بإرسال الطلب إلى خادم YMQ ، الموجود بالفعل في HTTP.
- يقوم خادم YMQ HTTP بتطبيق منطق SQS HTTP API ، ويقوم بالتحقق من صحة الطلب وترجمته إلى تنسيق protobuf مكتوب بقوة.
- YMQ Actor system - نظام الممثل . أطلقت في وقت واحد الآلاف من الجهات الفاعلة المختلفة تبادل المعلومات. نظام الممثل لكل مضيف هو جزء من الكتلة. جميع الجهات الفاعلة في المجموعة تعيش وتتصرف ككل. يتم تطبيق منطق الأعمال YMQ في مختلف الجهات الفاعلة المشاركة في طلبات المعاملات إلى YDB.
- أقراص YDB ("الأجهزة اللوحية") - جزء من YDB الأساسية ، المسؤولة عن العمل مع الجداول في الاستعلامات والمعاملات. الأجهزة اللوحية نفسها لا تخزن البيانات. هذه هياكل تحكم في الذاكرة يمكنها استعادة الحالة في حالة تعطل الأجهزة.
- التخزين هو تخزين موثوق وموزع ومقاوم للأخطاء.
تحتوي هذه البنية على عيب: تعمل كافة الخوادم في الكتلة بشكل مستقل مع جداول قائمة الانتظار نفسها. يؤثر هذا سلبًا على الأداء ويمنع تنظيم ذاكرات تخزين موثوقة للرسائل المخفية والقابلة للقراءة. من الصعب الحد من تدفق الطلبات ، وهذا مهم للغاية لأي خدمة محملة للغاية.
Yandex وضع قائمة انتظار بنية مع سادة قائمة الانتظار
أظهر إطلاق التحميل أن الإصدار الأول من البنية يقاوم حوالي 450 رسالة في الثانية الواحدة في قائمة الانتظار مع قشرة واحدة. كانت صغيرة جدا.
المشكلة الرئيسية كانت استفسارات التنافس. قام عدد كبير من المعاملات المتعارضة منطقياً بإحضار ذاكرة التخزين المؤقت للرسائل المخفية إلى حالة غير متناسقة. لحل المشكلة ، قدمنا كيان خاص - سيد قائمة الانتظار.
سيد قائمة الانتظار هو ممثل ، في ظل الظروف العادية ، موجود في كتلة في مثيل واحد ويمر عبر جميع الطلبات المرتبطة بقائمة انتظار معينة. إذا وصل طلب إلى قائمة الانتظار إلى خادم حيث يفتقد الرئيسي المطلوب ، يقوم ممثل بروكسي خاص بإعادة توجيه الطلب ثم ترجمة الاستجابة المستلمة من المعلم.
عند استخدام "معالج قائمة الانتظار" ، يقلل التخزين المؤقت الصحيح للرسائل غير المؤمّنة من التعارض عند العمل مع الجداول. يتم تبسيط تطبيق تقييد تدفق الطلبات ، على سبيل المثال ، من خلال
دلو Leaky . تتوفر مقاييس قائمة انتظار سريعة ودقيقة: عدد الرسائل ، إجمالي عدد الزيارات وما شابه. يمكنك تجميع طلبات مماثلة.
من الناحية النظرية ، فإن مثل هذه البنية لها عيوب معينة مرتبطة بالمركزية:
- تقليل التسامح مع الخطأ: في حالة فشل جهاز افتراضي مع رئيسي ، فلن تتوفر جميع قوائم الانتظار التي تحتوي على أساتذة. ومع ذلك ، فإن الآليات الخاصة لـ YDB تسمح لك برفع سادة جدد داخل المجموعة في بضع ثوانٍ فقط. هذا يحل المشكلة إلى حد كبير.
- قابلية التوسع: جميع الطلبات تمر عبر مضيف واحد. العيب هو تعادل أقراص YDB. يفعلون كل عمل شاق مع البيانات. يرسل السيد بشكل غير متزامن الطلبات ويعالج النتائج المستلمة. هذا يجعله كيانًا "خفيفًا الوزن" لا يخلق تأثير "عنق الزجاجة" أثناء اختبار الإجهاد.
قائمة انتظار معالج الاستعلام
تؤدي المعاملات الموزعة مع جداول قاعدة البيانات إلى تكاليف إضافية معينة ، لذا فإن فكرة تقليل عدد الاستعلامات تبدو منطقية بالنسبة لنا. مائة معاملة لتسجيل الرسائل واحدة في كل مرة من الأفضل أن تتحول إلى معاملة واحدة لتسجيل مائة رسالة في وقت واحد. مع قائمة انتظار الصفوف الرئيسية ، يعد تنفيذ معالجة الدُفعات (الدُفعات) أسهل بكثير.
الخلط يزيد بشكل طفيف الكمون أثناء العمليات. بدلاً من ذلك ، يتم زيادة عرض النطاق الترددي بشكل ملحوظ. مع الخلط ، يمكن لقائمة الانتظار الفردية أن تصل إلى 30.000 طلب في الثانية.
بشكل عام ، يمكن أن يكون تحميل قائمة الانتظار مختلفًا تمامًا: آلاف الرسائل في الثانية وعدة رسائل في اليوم. نحن بحاجة لتحسين العمل مع قوائم الانتظار باستخدام خوارزمية مرنة. الخيارات الأمامية مع تراكم الرسائل في المخزن المؤقت إلى رقم العتبة أو إعادة ضبط المؤقت لم تناسبنا. لذلك ، قمنا بتطوير خوارزمية تجميعية قابلة للتكيف لـ YMQ تعمل بشكل جيد في كلتا الحالتين. يظهر عمله في شكل جدول زمني.
هنا ، عند وصول رسالة جديدة ، يكون أحد السيناريوهات الثلاثة ممكنًا:
- تبدأ المعاملة على الفور في حالة عدم وجود معاملات أخرى من هذا النوع قيد التشغيل.
- إذا كان هناك بالفعل معاملات قيد التشغيل ، تتم إضافة الرسالة إلى المخزن المؤقت وينتظر إكمال المعاملات.
- إذا تجاوز حجم المخزن المؤقت قيمة العتبة ، يتم تشغيل معاملة متوازية أخرى. عدد المعاملات المتزامنة محدود.
تشبه فكرة الخلط التكيفي
خوارزمية Nagle لـ TCP / IP. : , latency . , . .
Yandex Message Queue, , . , , -.
YDB . YMQ .
, , , .
YMQ . . «» .
YDB . , , , «». , . .
: . , «» . -, «» , «», .
« » . , , .
Yandex Message Queue
Yandex Message Queue – - . . , . .
- - , , . .
- API , . , .
- , : , . , . . boto, 24/7, - .
- , , . .
. - . . .
:
.
في الختام
– , , , . ., ., ., . .
. .
,
Yandex Message Queue .