Kafka: partition, offset ও consumer group
Kafka Partitions, Offsets, and Consumer Groups
এই পাঠের সূচিপত্র
এই পাঠে যা শিখবেন
- Partition offset ও group বুঝুন
- Replay এবং retention পরিকল্পনা করুন
- Database side effect-এর সঙ্গে offset boundary মিলান
সমস্যা দিয়ে শুরু
E-commerce click events analytics ও fraud detection দুটো দল পড়বে। নতুন recommendation service গত সপ্তাহের event-ও চাইছে। Worker consume করলেই message মুছে ফেলা হলে এই history পাওয়া যায় না। স্বাধীন reader position দরকার।
সহজ করে বুঝি
Kafka topic partitioned append-only log। প্রতিটি partition-এ offset একটি record-এর অবস্থান; topic জুড়ে global sequence নয়। Consumer group নিজেদের মধ্যে partition ভাগ করে, আলাদা group স্বাধীনভাবে একই log পড়তে পারে। Retention policy অনুযায়ী data থাকে; consumer পড়েছে বলে সঙ্গে সঙ্গে মুছে যায় না।
পরিচিত একটি উপমা
একটি সংবাদপত্রের archive বহু পাঠক আলাদা bookmark দিয়ে পড়েন। একই গবেষণা দলের সদস্যরা archive-এর বিভাগ ভাগ করেন, অন্য দল আবার সব বিভাগ পড়তে পারে। Bookmark সরালেই পুরোনো সংবাদ পড়া যায়, যতক্ষণ archive থেকে মুছে যায়নি।
নকশাটি দেখুন
Diagram লোড হচ্ছে…
Diagram-এর text flow দেখুন
flowchart TD P[Laravel Events] --> T[Orders Topic] T --> A[Partition 0] T --> B[Partition 1] A --> G1[Analytics Group] B --> G1 A --> G2[Fraud Group] B --> G2
Producer key দিয়ে partition বাছতে পারে। একই partition-এর record order আছে; দুই partition-এর offset তুলনা করে global chronology বলা যায় না। Analytics ও fraud আলাদা group হওয়ায় position আলাদা। এক group-এর consumer বন্ধ হলে partition assignment rebalance হতে পারে।
PHP ও Laravel-এ প্রয়োগ
PHP consumer adapter থেকে record এসেছে ধরে Laravel handler fragment। Laravel core-এ Kafka queue driver ধরে নেওয়া যাবে না। kafka_inbox table-এ topic,partition_id,offset_id unique। Database transaction commit-এর পরে adapter offset commit করবে; crash হলে duplicate delivery inbox সামলাবে।
use Illuminate\Support\Facades\DB;
DB::transaction(function () use ($record) {
$inserted = DB::table('kafka_inbox')->insertOrIgnore([
'topic' => $record->topic,
'partition_id' => $record->partition,
'offset_id' => $record->offset,
]);
if ($inserted === 0) return;
DB::table('sale_events')->insert([
'event_id' => $record->eventId,
'amount_minor' => $record->amountMinor,
]);
});
// Commit this record's offset through the chosen Kafka client only now.
// Client offset APIs differ; database commit is not a Kafka transaction.এটি PHP 8.3+ ও Laravel 12-এর শিক্ষামূলক fragment; সম্পূর্ণ application নয়। সংশ্লিষ্ট route-এ authentication ও resource authorization প্রয়োগ করতে হবে। নিচের অনুশীলনে failure ইচ্ছা করে তৈরি করুন; শুধু সফল response দেখে correctness ধরে নেবেন না।
সুবিধা, সীমাবদ্ধতা ও trade-off
Replay ও independent groups নতুন consumer যোগ সহজ করে। Partition management, retention, consumer lag ও schema evolution operational দায় বাড়ায়। একই key-এর traffic খুব বেশি হলে hot partition হয়; শুধু consumer বাড়িয়ে ওই partition parallel করা যায় না।
সাধারণ ভুল
- Offset global event ID মনে করা।
- Consumer count partition-এর চেয়ে বাড়িয়ে linear speedup আশা করা।
- Offset আগে commit করে পরে database effect চালানো।
আরও একটু গভীরে
Kafka transaction consumed offsets ও Kafka-produced records নির্দিষ্ট processing boundary-তে atomic করতে পারে। External PostgreSQL update সেই একই transaction নয়। Event identity producer retry ও republish-তেও stable রাখা ভালো; partition-offset identity শুধু ওই log position চেনে।
Database commit-এর পরে offset commit-এর আগে consumer থামান। Restart-এ duplicate এলেও sale_events একবার চাই। নতুন group দিয়ে পুরোনো record পড়ুন। Retention পার হলে আর replay সম্ভব নয়; recovery requirement retention-এর আগে নির্ধারণ করুন।
মনে রাখুন
- Ordering partition scope-এ।
- Group position স্বাধীন।
- External effect-এর atomic boundary আলাদা।
নিজে চেষ্টা করুন
দশ partition-এর topic এবং তিন consumer-এর group-এর সম্ভাব্য assignment আঁকুন। এক consumer বন্ধ হলে ownership কীভাবে বদলাবে লিখুন।
নিজের বোঝা যাচাই করুন
1. Offset কি unique event identity?
Topic partition-এর অবস্থান; republish করলে একই business event নতুন offset পায়।
2. দুই group কী পায়?
প্রতিটি group নিজের position থেকে সব assigned partition পড়তে পারে, একে অন্যের message কেড়ে নেয় না।
3. Read করলে record মুছে যায়?
না। Retention ও compaction policy lifecycle ঠিক করে; consumer bookmark আলাদা।
4. Hot partition সমাধান?
Key distribution ও aggregation design বদলাতে হতে পারে; একই ordered partition সাধারণ group-এ একজন active consumer পায়।
5. Exactly-once database?
Kafka transaction-এর boundary external database ঢাকে না; inbox বা অন্য coordinated protocol দরকার।
আরও পড়ুন
এই পাঠের কুইজ
এই পাঠ থেকে ২টি প্রশ্ন। উত্তর দিয়ে ব্যাখ্যা দেখুন; অধ্যায়ের কুইজ আলাদাভাবে দিতে হবে।
এই পাঠের ২টি প্রশ্নের উত্তর দিন। পাস করতে দুটিই সঠিক হতে হবে।
জমা দেওয়ার পর সঠিক উত্তর ও ব্যাখ্যা দেখবেন। ফলাফল এই ব্রাউজারে সংরক্ষিত থাকবে। অনুশীলনের ফল অধ্যায় সম্পন্নের হিসাবে যোগ হয় না।
অগ্রগতি এই ব্রাউজারে সংরক্ষিত থাকে। শুধু পাঠ খুললে সম্পন্ন হয় না।