kafka
کافکا توی داکیومنت هاش خودش رو پلتفرم دیستربیوت استریم معرفی کرده. اینکه از message broker استفاده کنیم خوبیش loose coupling بین لایه های مختلفه
انواع دلیوری پیام در کافکا
- مدل at most once: یعنی یکبار پیام ارسال میشه و retry نداره و اگه از دست بره برای همیشه از دست میره مثلا برای فرستادن لاگ ویو صفحه خوبه
- مدل at least once: توی این مدل پیام بعد از دریافت توسط consumer کامیت میشه و بعدش پیام پردازش میشه توی این حالت retry داریم برای پیام های که هنوز کامیت نشدن
- مدل exactly once: توی حالت at least once اگه پیام کامیت بشه ولی وسط پردازش کرش کنه اون پیام چون کامیت شده دیگه retry نمیشه ولی توی این حالت بعد از پردازش کامییت میشه پس وقتی کامییت میشه یعنی پردازشش هم تموم شده. یعنی مثلا من یه ایونت میفرستم، پردازشم شروع میشه یه پیام توی یه جایی که برای خوده کافکا است پابلیش میشه بعد اینکه کارم تموم شد کامییت که کردم میره داخل همون جایی که برای کافکا بود میکه کارش تموم شد این ایونت و اگه fail بشه کافکا پاکش میکنه
وقتی پیام پابلیش میشه چه اتفاقاتی میافته؟ وقتی یک پیام در Kafka publish میشود، producer اول تصمیم میگیرد که پیام باید روی کدام partition برود. این انتخاب یا بر اساس key انجام میشود یا اگر key نداشته باشد، با round-robin یا الگوریتم دیگر. بعد از مشخص شدن partition، producer پیام را برای leader broker آن partition میفرستد.
broker پیام را به انتهای log مربوط به آن partition اضافه میکند. این log یک فایل append-only روی دیسک است که به صورت segment تقسیم شده. داده بلافاصله در حافظه سیستمعامل (page cache) ذخیره میشود و بعد به صورت پسزمینه روی دیسک flush میشود، به همین دلیل هم Kafka خیلی سریع عمل میکند.
بعد از نوشتن پیام، leader آن را برای replicaهای follower ارسال میکند تا کپیها بهروز شوند. بسته به تنظیمات producer، ممکن است منتظر تأیید همه replicaها بماند یا فقط منتظر تأیید leader باشد. زمانی که شرط acks برآورده شد، leader یک acknowledgment به producer میفرستد که شامل offset پیام در log هم هست.
از این لحظه پیام رسماً در Kafka ذخیره شده و آماده مصرف است. consumerها با استفاده از offsetها پیام را از log میخوانند. Kafka پیام را تا زمانی که retention policy اجازه دهد نگه میدارد، حتی اگر همه consumerها آن را خوانده باشند.
به این ترتیب، publish یک پیام در Kafka زنجیرهای از انتخاب partition، append شدن روی log، replication بین brokerها و در نهایت برگرداندن acknowledgment به producer است.
Broker
اBrokerها در واقع سرورهای Kafka هستن که دادهها رو نگه میدارن و مدیریت میکنن. هر broker میتونه چند topic و partition رو میزبانی کنه. وقتی من پیام میفرستم، broker وظیفه داره پیام رو ذخیره کنه، replicate کنه و در دسترس بقیه consumerها بذاره. وقتی cluster از چند broker تشکیل میشه، هر broker با بقیه هماهنگ میکنه تا اگه یکی از کار افتاد، دادهها همچنان در دسترس باشن. این replication باعث میشه Kafka خیلی مقاوم و fault-tolerant باشه.
Topics
تاپیک مثل یه کانال یا دستهبندهست که پیامها رو بر اساس موضوع جدا میکنه. فرض کن میخوای لاگهای صفحه، سفارشهای خرید و هشدارهای سیستم رو جدا ذخیره کنی، هر کدوم یه topic میشن. من وقتی پیام میفرستم، مشخص میکنم به کدوم topic بره. consumerها هم میتونن subscribe کنن به topic دلخواه و فقط پیامهای مربوطه رو بخونن. Topic در واقع یک نام منطقیه که پیامها رو گروهبندی میکنه، ولی خودش داده رو ذخیره نمیکنه—این partitionها هستن که نگهداری میکنن.
Partitions
هر topic میتونه به چند partition تقسیم بشه تا همزمان پردازش سریعتر بشه و مقیاسپذیر باشه. Partition مثل یه خط زمانیه، هر پیام که میفرستم میره ته این خط و یه offset یکتا میگیره. هر partition یه leader داره و followerها اون partition رو replicate میکنن. این ساختار باعث میشه که حتی وقتی پیامها خیلی زیاد شدن یا brokerها crash کردن، دسترسی به دادهها از بین نره. partition همچنین امکان parallelism رو فراهم میکنه: چند consumer میتونن همزمان روی partitionهای مختلف پیامها رو پردازش کنن.
The Commit Log
کامیت لاگ همون دنباله پیامهای append-only هست که هر partition داره. وقتی پیام publish میشه، میره ته log و offset یکتا میگیره. log تضمین میکنه که پیامها همیشه پشت سر هم و با ترتیب درست ذخیره میشن. Consumerها بر اساس offset میتونن پیامها رو بخونن و حتی بعد از چند روز یا هفته دوباره برگردن پیامها رو مرور کنن. Kafka هیچ پیام رو حذف نمیکنه تا وقتی که retention policy اجازه بده، حتی اگر همه consumerها پیام رو خونده باشن. این log همچنین پایهایه برای replication، recovery و exactly-once semantics، چون همه دادهها مرتب و قابل دسترس باقی میمونن.
Retention policy توی Kafka همون قانونی هست که مشخص میکنه پیامها تا چه مدت یا تا چه حجمی توی topic نگه داشته بشن. یعنی Kafka خودش به صورت خودکار بعد از یه مدتی یا وقتی حجم log به حد مشخص رسید، پیامهای قدیمی رو پاک میکنه تا حافظه پر نشه.
میتونه بر اساس زمان باشه، مثلاً پیامها ۷ روز نگه داشته بشن، یا بر اساس حجم، مثلاً وقتی log یه partition به ۱۰ گیگ رسید، پیامهای قدیمی شروع به حذف شدن میکنن. این سیاست باعث میشه حافظه و دیسک broker پر نشه و عملکرد Kafka ثابت بمونه.
نکات طراحی Producer
پرودیسر مسئول اینه که پیامها رو به Kafka بفرسته. هر تصمیمی که اینجا میگیریم، مستقیم روی سرعت و اطمینان ورود دادهها تاثیر داره.
الف) امنیت و دوام دادهها
برای اینکه دادهها گم نشن یا درست ثبت بشن، مهمترین گزینه acks هست:
-
ا
acks=allیاacks=-1: بیشترین امنیت، منتظر میمونه تا همه replicaهای فعال پیام رو تایید کنن. عالیه برای دادههای مهم مثل لاگهای حساس ولی کمی کندتره. -
ا
acks=0: سریعترین حالت، هیچ تاییدی نمیخواد ولی ممکنه داده گم بشه. فقط وقتی مهم نیست دادهها از دست برن استفاده میکنیم (مثلاً page view تو وب).
Retries و Idempotence:
- اRetries: اگه شبکه یه لحظه قطع شد، producer خودش تلاش میکنه دوباره بفرسته.
-ا Idempotence: با فعال کردن enable.idempotence=true، اگه پیام دوباره فرستاده بشه، فقط یکبار ثبت میشه و از Duplicate جلوگیری میکنه.
ب) ترتیب پیامها و همزمانی
اگه ترتیب پیامها مهم باشه (مثل سیستمهای audit یا تراکنش):
- باید
max.in.flight.requests.per.connection=1وacks=allباشه تا پیامهای بعدی قبل از تایید پیام قبلی ارسال نشن.
ج) گروهبندی و مسیردهی دادهها
-ا Keying: اگه میخوایم پیامهای مرتبط تو یه partition باشن، از key استفاده میکنیم. مثلا stage ID برای alert trend data.
- اCustom Partitioner: اگه بخوایم کنترل کنیم کدوم partition داده بره، partitioner کلاس میسازیم. مثلا همه alertهای مهم برن تو partition 0 تا سریعتر پردازش شن.
نکات طراحی Consumer
کانسیومر مشخص میکنن دادهها چجوری خونده، پردازش و دنبال میشن و چهقدر اپلیکیشن مقیاسپذیر باشه.
-
اConsumer Group (
group.id): همه consumerهایی که group id مشترک دارن، کار رو بین خودشون تقسیم میکنن → throughput بالا. -
تعداد consumerها نباید بیشتر از partition باشه، وگرنه بعضی idle میشن.
چرا کافکا در نوشتن بهینه است؟
کافکا تو نوشتن خیلی بهینه است چون همیشه پیامها رو به ته فایل اضافه میکنه و دنبال جاهای خالی یا overwrite نمیگرده، این باعث میشه نوشتن روی دیسک خیلی سریع باشه. پیامها رو دستهای (batch) میفرسته و مینویسه، نه یکییکی، بنابراین تعداد عملیات روی دیسک و شبکه کم میشه و CPU کمتر درگیر میشه. وقتی میگم Kafka پیامها رو دستهای (batch) میفرسته و مینویسه، منظورم اینه که producer چند تا پیام رو جمع میکنه و یکجا به broker میفرسته. بعد broker این batch رو اول تو حافظه (page cache سیستم عامل) مینویسه نه مستقیم روی دیسک.
کافکا از تکنیک zero-copy و page cache سیستم عامل استفاده میکنه، یعنی دادهها مستقیم از حافظه فایل سیستم به شبکه میرن بدون کپی اضافه، سرعت بالاتر و مصرف CPU پایینتر میشه. همچنین consumerها هم پیامها رو به ترتیب و پشت سر هم میخونن، که sequential read خیلی سریعتر از random read هست. در نهایت، هر topic میتونه چند partition داشته باشه و هر partition مثل یه log مستقل عمل میکنه، پس نوشتن و خوندن میتونه همزمان و موازی انجام بشه. به زبان ساده، Kafka مثل یه خط تولید مرتب و بدون برگشت کار میکنه؛ همه چیز تو حافظه و دیسک بهینه پیش میره و throughput خیلی بالاست.