تشغيل Kafka في بيئة الإنتاج
تشغيل Kafka في بيئة الإنتاج
تشغيل Kafka على نطاق واسع في الإنتاج يتجاوز بكثير مجرد "تشغيل الوسيط ونشر الرسائل". أربعة قرارات تحكم صحة الكلستر يومياً: كيفية تحديد أحجام الأقسام، ومدة الاحتفاظ بالبيانات، وما إذا كان الضغط مفعّلاً، وما إذا كان تأخر المستهلك وصحة ISR تُراقَب بالقرب الفعلي من الوقت الحقيقي. أخطأ في أي منها وستواجه استنزاف الأقراص، وانحراف المستهلك غير المكتشف، وخسارة البيانات الصامتة — وغالباً الثلاثة في الوقت نفسه.
تحديد حجم الأقسام
الأقسام هي وحدة التوازي والنسخ المتماثل واستهلاك معالجات الملفات. الخطأ في العدد عند إنشاء الموضوع مكلف الإصلاح لاحقاً لأن إعادة التقسيم تتطلب ترحيل بيانات كامل.
معادلة الإنتاجية. عدد الأقسام المستهدف = max(Tin / p, Tout / c)، حيث Tin هو الإنتاجية القصوى للاستيعاب بالميغابايت/ثانية، وp هو إنتاجية الكتابة لكل قسم (~10 MB/s على NVMe)، وc هو إنتاجية المستهلك لكل قسم. موضوع يستقبل 500 MB/s بـ5 خيوط مستهلك يحتاج 12 قسماً مع هامش نمو.
تكلفة معالجات الملفات. كل نسخة قسم تفتح معالجَي ملف (فهرس + مقطع). وسيط يستضيف 50 000 نسخة قسم يحتاج 100 000 معالج ملف على الأقل؛ اضبط ulimit -n 200000 في وحدة systemd وfs.file-max بالقدر المناسب.
إعادة توزيع الأقسام. عند الحاجة لإعادة التقسيم، استخدم kafka-reassign-partitions.sh مع معاملات خنق حركة البيانات حتى لا يُشبع إعادة التوازن شبكة الوسطاء. معدل خنق النسخ 50 MB/s محافظ لكن آمن للكلستر الخادم.
سياسات الاحتفاظ بالبيانات
الاحتفاظ هو ميزانية تخزين، لا استراتيجية نسخ احتياطي. بُعدان يتحكمان فيه: زمني (retention.ms) وحجمي (retention.bytes). كلاهما يُطبَّق لكل قسم؛ الحد الأقصى لحجم الموضوع هو retention.bytes * عدد_الأقسام. يُطبَّق أيهما بلغ أولاً.
دوران المقاطع. يُطبَّق الاحتفاظ بدقة المقطع لا الرسالة. لا يُحذف المقطع إلا إذا كان أقدم من retention.ms وتوجد مقاطع أحدث. المقطع النشط (المفتوح) لا يُحذف أبداً. موضوع منخفض الحجم مع segment.ms كبير يمكن أن يحتفظ بالبيانات أطول بكثير مما يشير إليه retention.ms. لمواضيع التدقيق، اضبط segment.ms قريباً من retention.ms / 2.
التخزين المتدرج. تقدم كل من Confluent وAWS MSK تخزيناً متدرجاً حيث تُنقل المقاطع الأقدم من عتبة ما إلى تخزين الكائنات (S3/GCS)، مع إبقاء البيانات الحارة الأخيرة على NVMe محلي. هذا يفصل تكلفة التخزين عن توسيع الحوسبة وهو النمط الموصى به للمواضيع ذات الاحتفاظ بالأسابيع أو الأشهر.
ضغط السجل (Log Compaction)
الضغط يحتفظ بأحدث سجل لكل مفتاح، متجاهلاً السجلات الأقدم تدريجياً. هو الخيار الصحيح لمواضيع سجل التغييرات (CDC قواعد البيانات، حالة الكيانات) حيث يحتاج المستهلكون لأحدث قيمة لا للتاريخ الكامل. إنه الخيار الخاطئ لتدفقات الأحداث حيث يهم الترتيب ضمن نافذة زمنية.
يعمل الضغط في خيوط خلفية تتحكم فيها log.cleaner.threads (الافتراضي 1، ارفع إلى 4-6 في الكلسترات الكبيرة). المنظف يستهدف الأقسام التي تتجاوز نسبة "القذارة" الخاصة بها (بايتات غير مضغوطة / إجمالي البايتات) القيمة min.cleanable.dirty.ratio. للضغط العدواني على مواضيع CDC المنخفضة الكمون، خفّض هذه القيمة إلى 0.1.
علامات الحذف (Tombstones). السجل ذو قيمة null هو علامة حذف — يُشير لحذف ذلك المفتاح. تُحفظ علامات الحذف لمدة لا تقل عن delete.retention.ms (الافتراضي 24 ساعة) حتى يلحق المستهلكون قبل اختفاء المفتاح كلياً.
cleanup.policy=compact,delete يطبق كليهما: يعمل الضغط وتُحذف المقاطع بعد retention.ms. هذا يعني أن حتى "أحدث" قيمة لمفتاح يمكن أن تختفي إذا كان الموضوع صغيراً بما يكفي ليسبق الحذفُ الضغطَ. للدلالات النقية للسجل، استخدم cleanup.policy=compact فقط.
مراقبة تأخر المستهلك
تأخر المستهلك هو الفرق بين إزاحة نهاية السجل (LEO) والإزاحة المُثبَّتة لكل قسم. تأخر يتزايد باستمرار هو أول علامة على مستهلك غير قادر على المواكبة؛ تأخر ذو تذبذب يشير إلى معالجة انفجارية. كلاهما يستدعي تدخلاً لكن الاستجابة تختلف.
الأدوات الأصلية. kafka-consumer-groups.sh --describe يُظهر التأخر لكل قسم وتعيين المستهلك. صحيح لكنه لقطة آنية؛ يفوته التأخر الذي يتذبذب ويتعافى بين الاستطلاعات.
تكامل Prometheus. نشر kafka-exporter أو مُصدِّر JMX من Confluent. المقياس الحرج هو kafka_consumergroup_lag لكل مجموعة/موضوع/قسم. يُنبَّه على: إجمالي التأخر يتجاوز 10× حالة الاستقرار الطبيعية، معدل تغيّر التأخر موجب لأكثر من 5 دقائق، أي قسم بتأخر > 0 ولا يوجد له مستهلك نشط.
مراقبة ISR (النسخ المتزامنة)
مجموعة ISR هي المؤشر الحتمي لصحة النسخ المتماثل. عندما تسقط نسخة من ISR — لأنها متأخرة أكثر من replica.lag.time.max.ms (الافتراضي 30 ثانية) عن القائد — يعمل الكلستر دون ضمان المتانة. إذا كان موضوعك مع min.insync.replicas=2 وRF=3 يفقد نسختين من ISR، سيُحجب جميع المنتجين ذوي acks=all بخطأ NotEnoughReplicasException.
مقاييس JMX الرئيسية للتنبيه عليها:
kafka.server:type=ReplicaManager,name=UnderReplicatedPartitions— أي قيمة فوق 0 تنبيه من الأولوية الأولى في العمليات الطبيعية.kafka.server:type=ReplicaManager,name=IsrShrinksPerSec— معدل موجب يعني أن النسخ تتأخر بنشاط؛ تحقق فوراً من الشبكة وإدخال/إخراج القرص وGC على الوسيط المتأخر.kafka.controller:type=KafkaController,name=ActiveControllerCount— يجب أن يكون 1 بالضبط.kafka.network:type=RequestMetrics,name=RequestsPerSec,request=Produce— أسِّس خطاً أساسياً للكشف عن ارتفاعات حركة المرور التي تسبق انكماش ISR.
UnderReplicatedPartitions = 0 وأن جميع مجموعات المستهلكين لا تعاني من تأخر في المواضيع الحرجة. أدمج هذه الفحوصات في خط أنابيب النشر كما تدمج فحوصات جاهزية حاويات Kubernetes.
أنماط دفتر التشغيل
يُشفّر المهندسون المتقدمون ردود أفعالهم على انكماش ISR والتأخر المتصاعد كخطوات في دفتر التشغيل، لا كحدس:
- انكماش ISR على وسيط واحد. تحقق من
iostat -xz 1وسجلات GC على ذلك الوسيط. إذا تجاوز انتظار I/O القرص 80%، الوسيط يُفرغ السجل بشكل متسارع — تأكد من أن مسح ذاكرة التخزين المؤقت للصفحات يتولى المهمة. - تأخر المستهلك يتزايد بثبات. أضف نسخ المستهلك حتى عدد الأقسام (أبعد من ذلك تكون خاملة). تحقق مما إذا كانت المعالجة مقيدة بالمعالج أو الإدخال/الإخراج. إذا كانت مقيدة بالإدخال/الإخراج (استدعاءات قاعدة بيانات خارجية)، افصل مع مجمّع عمال غير متزامن.
- استنزاف القرص. طارئ: خفّض
retention.bytesعلى أكبر المواضيع، أو أطلق حذف مقاطع مبكراً عبرkafka-delete-records.sh. على المدى البعيد: أضف وسطاء وأعد توازن الأقسام.
unclean.leader.election.enable=true (معطّل افتراضياً منذ Kafka 0.11)، تتبادل الاتساق بالتوافر — يمكن لنسخة متأخرة أن تصبح قائداً، مسببةً خسارة رسائل. هذا غير مقبول أبداً للمواضيع المالية أو موضوعات التدقيق. لأعباء العمل عالية التوافر التي تتحمل إعادة المعالجة (استيعاب المقاييس، تدفق النقرات)، يمكن تفعيله كملاذ أخير خلال حدث خسارة كاملة لـ ISR، لكن وثّق ذلك كقرار معماري صريح وعُد عنه فور التعافي.