معمارية كافكا للمشغّلين
معمارية كافكا للمشغّلين
Apache Kafka هو سجل توزيعي (commit log) يتنكر في هيئة وسيط رسائل. فهم معماريته الداخلية — ليس فقط كيفية استخدامه من منظور المنتج أو المستهلك، بل كيف تُخزَّن البيانات وتُنسَخ وتُنسَّق عبر الكتلة — هو ما يميز المشغّلين القادرين على إبقاء كتلة Kafka سليمة على نطاق واسع عن أولئك الذين يُستدعون في الثالثة صباحًا دون أن يعرفوا من أين يبدؤون. يرسم هذا الدرس المعمارية الداخلية بالكامل: الوسطاء، والمواضيع، والأقسام، والنسخ المتماثلة، والمتحكم — بمستوى من التفصيل يُمكّنك من استيعاب أسباب الفشل في الإنتاج قبل وقوعها.
الوسطاء: وحدة التوسع
الوسيط في Kafka (broker) هو عملية JVM عادية تعمل على مضيف. مهمته تخزين وخدمة مقاطع السجلات للأقسام المخصصة له. تعمل الكتلة الإنتاجية في كبرى شركات التقنية على ما بين 12 ومئات الوسطاء، عادةً على مضيفات مخصصة مع NVMe محلية أو نسخ محسَّنة عالية الإنتاجية. يُعرَّف كل وسيط برقم broker.id، أو في وضع KRaft برقم UUID يؤدي الغرض ذاته.
يخزّن الوسيط بيانات الأقسام على القرص كملفات مقاطع غير قابلة للتغيير تعمل بالإلحاق فقط. كل مقطع عبارة عن زوج: ملف .log يحتوي على بايتات الرسائل الخام، وملف .index يعيّن الإزاحات إلى مواقع البايت. عندما يصل المقطع إلى الحجم المضبوط في log.segment.bytes (الافتراضي 1 غيغابايت)، يُحدَّث إلى مقطع نشط جديد. لا يعيد الوسيط الكتابة فوق المقاطع الموجودة أبدًا — يُلحق فقط ثم يحذف المقاطع القديمة عبر سياسة الاحتفاظ. هذا هو جوهر التصميم الذي يجعل Kafka سريعًا: الإدخال/الإخراج المتسلسل أسرع بمرتبة عن الإدخال/الإخراج العشوائي.
acks=all). نموذج التخزين القائم على السجل يعني أن التعافي بعد تعطل هو ببساطة إعادة التشغيل من آخر إزاحة مُودَعة.
إعدادات الوسيط الحيوية التي يجب على كل مشغّل معرفتها:
المواضيع والأقسام والسجل
الموضوع هو تغذية منطقية من السجلات. إنه مساحة أسماء، لا وحدة تخزين. تعيش جميع البيانات الفعلية في الأقسام. عندما تنشئ موضوعًا بـ --partitions 12، تُنشئ 12 سجلًا مستقلًا مرتبًا بالإلحاق فقط موزعة عبر الكتلة. يُخزَّن كل قسم على وسيط واحد بالضبط في أي لحظة (القائد)، مع نسخ على وسطاء إضافيين (المتابعون/النسخ).
يحدد عدد الأقسام الحد الأقصى للتوازي في الاستهلاك: لا يمكن لمجموعة مستهلكين أن يكون لها أكثر من مستهلك نشط واحد لكل قسم. إذا كان لديك 12 قسمًا و20 مستهلكًا في مجموعة، سيكون 8 مستهلكين خاملين. عدد الأقسام دائم في اتجاه الزيادة — يمكنك زيادة الأقسام لكن لا يمكنك إنقاصها، وزيادة الأقسام تكسر الترتيب المبني على المفاتيح للمستهلكين الموجودين. حدد عدد الأقسام بشكل صحيح عند الإنشاء.
النسخ المتماثلة: مجموعة ISR وعقد الدوام
النسخ المتماثلة في Kafka قائمة على الجلب (pull-based): تجلب نسخ المتابعين باستمرار من القائد، لا العكس. لكل قسم وسيط قائد واحد بالضبط وصفر أو أكثر من وسطاء المتابعين. يشكّل هؤلاء مجتمعين مجموعة النسخ. الجزء من النسخ المتزامن مع القائد يُسمى مجموعة النسخ المتزامنة (ISR).
مجموعة ISR هي قلب ضمان الدوام في Kafka. عندما يرسل منتج بـ acks=all، لا يُقرّ القائد الكتابة حتى يحفظ كل وسيط في مجموعة ISR الرسالة. إذا تخلف متابع بأكثر من replica.lag.time.max.ms (الافتراضي 30 ثانية)، يُزال من مجموعة ISR، مما يُدهور مستوى التكرار لديك بصمت.
الثابت الحيوي للمشغّل: min.insync.replicas هو الحد الأدنى. إذا انكمشت مجموعة ISR دون هذه القيمة، سيتلقى المنتجون الذين يستخدمون acks=all خطأ NotEnoughReplicasException ويصبح القسم للقراءة فقط. هذا مقصود: الرفض أفضل من القبول مع دوام غير كافٍ.
المتحكم: عقل الكتلة
المتحكم (controller) هو وسيط واحد مُنتخب لإدارة بيانات التعريف الخاصة بالكتلة وتنسيق قيادة الأقسام. في المعمارية القديمة القائمة على ZooKeeper، كان المتحكم يُنتخب عبر عقدة ZooKeeper مؤقتة. في الوضع الحديث KRaft (Kafka 3.3+ إصدار GA، إلزامي في Kafka 4.0+)، أُزيل ZooKeeper كليًا. المتحكم الآن هو مجموعة إجماع قائمة على Raft: مجموعة صغيرة من الوسطاء (عادةً 3 أو 5) تُشكّل نصابًا. سجل البيانات الوصفية — كل إنشاء موضوع، وإعادة تعيين قسم، وتسجيل وسيط، وتغيير ISR — هو قسم Kafka بحد ذاته مُنسوخ عبر هذا النصاب. هذا يجعل تبديل المتحكم يستغرق أقل من ثانية.
مسؤوليات المتحكم:
- انتخاب القائد: عند فشل قائد قسم، يختار المتحكم النسخة المتزامنة التالية للترقية.
- تسجيل الوسطاء: عند بدء وسيط أو تعطله، يُسجّل/يُلغي التسجيل مع المتحكم.
- تغييرات ISR: تُبلّغ الوسطاء المتحكمَ بأحداث انكماش/توسع ISR.
- إدارة المواضيع والأقسام: جميع العمليات الإدارية تمر عبر المتحكم.
توزيع الأقسام والوعي بالرف
يوزع Kafka نسخ الأقسام عبر الوسطاء لموازنة حمل القيادة وتحمّل إخفاقات الوسطاء. في عمليات النشر متعددة المناطق أو الرفوف، تحتاج إلى الوعي بالرف (rack awareness) لضمان أن كل قسم له نسخ في نطاقات إخفاق مادية مختلفة.
اضبط broker.rack على كل وسيط ليطابق منطقة التوافر أو تسمية الرف المادي. عند إنشاء موضوع، سيضمن Kafka أن مجموعة النسخ لكل قسم تمتد عبر رفوف مختلفة، مما يعني أن فقدان منطقة توافرية كاملة لن يُسبب فقدان بيانات.
--throttle بقيمة تساوي 20-30% من عرض النطاق بين الوسطاء.
أنماط الفشل الرئيسية التي يجب على كل مشغّل معرفتها
انتخاب القائد غير النظيف: إذا كان unclean.leader.election.enable=true وكانت جميع أعضاء ISR معطلة، يمكن لـ Kafka انتخاب نسخة غير متزامنة كقائد — وهذا يُسبب فقدان بيانات. اضبط هذا على false في جميع الكتل الإنتاجية دون استثناء.
عاصفة المتحكم: إعادة تشغيل الوسطاء بسرعة يمكن أن تُطلق انتخابات متحكم متكررة. الأعراض: يرى المنتجون والمستهلكون أخطاء NOT_LEADER_OR_FOLLOWER المتكررة. التخفيف: فرّق إعادات تشغيل الوسطاء بـ 30-60 ثانية على الأقل.
إخفاق دليل السجل: إذا فقد وسيط قرصًا، تُوقَف جميع الأقسام على ذلك الدليل. يدعم Kafka 1.1+ مفهوم JBOD: اضبط عدة مدخلات log.dirs تشير إلى أقراص منفصلة. إخفاق قرص لا يُوقف الوسيط بالكامل — فقط الأقسام الموجودة على ذلك القرص.
UnderReplicatedPartitions — يجب أن يكون 0 في الحالة الثابتة. (2) ActiveControllerCount — يجب أن يكون 1 بالضبط. (3) OfflinePartitionsCount — يجب أن يكون 0. (4) RequestHandlerAvgIdlePercent — يجب أن يبقى فوق 30%؛ انخفاضه تحت 20% يُشير إلى أن الوسيط مثقل بـ CPU. اربط هذه المقاييس بمنظومة تنبيه Prometheus الموجودة لديك.
الخلاصة
معمارية Kafka هي مجموعة من المقايضات المتعمدة: ملفات المقاطع بالإلحاق فقط للإنتاجية، والنسخ المتماثلة القائمة على الجلب عبر ISR للدوام دون عرقلة المنتجين، ومتحكم مركزي قائم على Raft في KRaft للبيانات الوصفية المتسقة، وتعيين أقسام يراعي الرف لعزل الأعطال. كل نمط فشل إنتاجي — الانتخابات غير النظيفة، وانكماش ISR، وعواصف المتحكم، وإخفاقات دليل السجل — ينبع مباشرة من هذه القرارات التصميمية. المشغّلون الذين يفهمون المعمارية يقرؤون الإخفاق من المقاييس والسجلات في ثوانٍ. في الدرس التالي ننتقل إلى جانب المنتج والمستهلك: كيف تُجمَّع الكتابات وتُضغط وتُودَّع، وكيف تُنسّق مجموعات المستهلكين تعيين الأقسام.