کافکا ابزاری قدرتمند برای پیادهسازی معماری Publish/Subscriber است که برای pipeline کردن دادهها و Stream Processing استفاده میشه. که تمام اینها در کنار مقیاسپذیر بودن و fault-tolerant بود اون رو به یکی از ابزارهای اصلی در کلاندادهها تبدیل کرده.
فرض کنید تعدادی سرویس نیاز دارند که با همدیگه صحبت کنند و همدیگر رو مستقیما call میکنند. پیچیدگی فنی زیاد میشه، کوچکترین تغییری رو به سختی باید در همه سرویسها دنبال کرد و پیادهسازی back pressure هم که خودش داستانی جدا برای هر سرویس داره. در نهایت این یک بدهی فنیه که باید پرداخت بشه. یکی از معماریها برای حل این مشکل، Pub/Sub است. سرویسها دادههایی رو Publish میکنند و کسایی که به اون دادهها نیاز دارند Subscribe میکنند.
اوایل معرفی از کافکا به عنوان کامیتلاگ توزیعشده اسم برده میشد، چیزی که این روزها به بستر استریمینگ توزیعشده تغییر پیدا کرده. اطلاعات نوشته شده در کافکا بهترتیب هستند و روی دیسک ذخیره میشند.
پیامهای نوشته شده در کافکا توسط topic دستهبندی میشند. شاید topic را بشه معادل یک جدول در بانک اطلاعاتی دونست. هر topic به تعدادی partioion تقسیم میشه که از منطق append only پیروی میکنند و هر پیام در هر partiotion یک id یکتا بهش اختصاص پیدا میکنه. وقتی تولید کننده پیام (producer) قصد نوشتن در یک topic رو داره، میتونه partition رو صریحا اعلام کنه (این پیام رو در پارتیشن شماره ۳ بنویس) یا اینکار بر اساس هش از کلید پیام انجام بشه.
در مقابل producer ها، consumer ها قرار میگیرند که شروع به خوندن اطلاعات از kafka میکنند و بر اساس اون کاری رو انجام میدهند. consumer ها بر اساس کاری که انجام میدهند به گروههای مختلفی تقسیم بندی میشند که بهش consumer group گفته میشه و هر partition حداکثر به یک consumer از هر گروه اختصاص پیدا میکنه. یعنی اگر شما تعداد پارتیشنها رو ۱۰ تا انتخاب کنید و ۲۰ تا consumer داشته باشید، ۱۰ تا از consumer هاتون عملا بیکارند. پس یکی از موراد مهم در طراحی انتخاب تعداد پارتیشن مناسب هست.
به هر سرور کافکا Broker گفته میشه. هر سرور میتونه حاوی چندین topic و به ازای هرکودوم هم حاوی چندین partition باشه. طراحی Broker ها بهنحویه که بتونند بهعنوان یک خوشه (cluster) کار کنند. در این مواقع یکی از سرورها به عنوان controller انتخاب میشه و وظیفه داره مشخص کنه که کدام partition به کدوم بروکر اختصاص داره، همینطور وظیفه health check و مانیتور کردن بقیه سرورها هم بر عهده controller هست. بر اساس تنظیمات ممکنه یک partition به بیش از یک سرور اختصاص پیدا کنه که به معنی replication است. فرض کنید پارتیشن X از تاپیک Y به ۳تا سرور A,B و C اختصاص داره. یکی از این ۳تا سرور به عنوان leader برای این partition انتخاب میشند و دوتای دیگه replicate های اون هستند. این کار کمک میکنه تا در صورت از دست دادن leader چندین copy از اطلاعات اون وجود داشته باشه تا consumer ها بعد از re-balance شدن بهکار خودشون ادامه بدند.
کافکا طراحی نشده که همزمان روی چندین دیتاسنتر اجرا بشه، یعنی یکی از بروکرهای کلاسترمون رو دیتاسنتر A باشه و دیگری روی دیتاسنتر B. ولی ممکنه ما نیاز داشته باشیم که اطلاعاتمون رو چندین دیتا سنتر باشند. چرا؟ امنیت، isolation و disaster recovery
برای اینکار کافکا ابزاری داره به اسم Mirror Maker که مثل یک consumer/producer عمل میکنه. یعنی عملا از یکی از کلاسترها میخونه و در یکی دیگه مینویسه. پاک کردن اطلاعات از کافکا اینطوری نیست که بگیم فلان id رو پاک کن! بلکه بر اساس استراتژی خاصی اطلاعات از کافکا پاک میشند.
۱) بر اساس زمان: من اطمینان دارم که حداکثر ۷ روز طول میکشه تا اطلاعات پردازش بشند، پس به کافکا میگم که اطلاعاتی که قدیمیتر از ۷ روز هستند رو پاک کنه. چطوری این اتفاق میافته؟ خوب کافکا اطلاعات هر پارتیشن رو فایل به فایل مینوسه. مثلا بهش میگیم حجم هر فایل ۱ گیگ بشه، اطلاعات به پارتیشن X میرسند و شروع به نوشتن در فایل T1P1F1 میکنه (یک اسم فرضی، یعنی Topic اول، Partition اول و فایل اول) . وقتی به حجم فایل ۱ گیگ شد، این فایل رو میبنده و میره سراغ فایل بعدی. حالا این فایل مقدار modified at داره و در صورتی که این تاریخ قبل از ۷ روز پیش باشه، پاک میشه. برای همین ممکنه آخرین پیام نوشته شده مربوط به ۵ روز پیش باشه و اولین مربوط به ۱۰۰ روز پیش. خوب فایل پاک نمیشه و ما هنوز امکان دسترسی به اطلاعات قدیمیتر از ۷ روز رو هم داریم (در این پارتیشن)
۲) بر اساس حجم: من ۱ ترا حجم حجم به کافکا اختصاص دادم و بهش میگم حجم اطلاعاتت رو روی ۸۰۰ گیگ نگاهدار. در اینجور مواقع در صورتی که ۸۰۰ گیگ رد بشه، کافکا قدیمیترین فایل رو پاک میکنه. این مدل قابل ترکیب با مدل زمانی هست. هر کودوم زودتر اتفاق بیفته، بر اساس اون سیاست حذف انجام میشه.
۳) فشرده (compact): در این حالت از هر partition به عنوان key-value استفاده میشه و هر پارتیشن فقط آخرین پیام رو نگاه میداره. از این روش برای نگاهداشتن index مکانی که consumer ازش خونده استفاده میشه. یعنی اگر consumer به هر دلیل reset شد و نمیدونست تا کجا خونده، این پیام رو میخونه و از اونجا به بعد رو شروع به پردازش میکنه. (تاپیکها متفاوت هستند)