Message Queues
- ●Message Queue হলো producer আর consumer-এর মধ্যে একটা মধ্যস্থ broker, যা কাজকে async ও decoupled করে।
- ●মূল দুই প্যাটার্ন — point-to-point (এক consumer) আর pub/sub (অনেক consumer)।
- ●Delivery guarantee (at-least-once, at-most-once, exactly-once), backpressure আর dead-letter queue — এগুলোই বাস্তব সিস্টেমের মূল বিবেচ্য।
সমস্যাটা কী?
ধরো তোমার একটা ই-কমার্স অ্যাপ আছে। কেউ অর্ডার দিলে তোমাকে — (১) পেমেন্ট নিশ্চিত করতে হবে, (২) ইনভয়েস বানাতে হবে, (৩) কনফার্মেশন ইমেইল পাঠাতে হবে, (৪) ইনভেন্টরি আপডেট করতে হবে, (৫) SMS পাঠাতে হবে।
যদি এই সব কাজ একই request-এর ভেতরে এক এক করে synchronously করো, ব্যবহারকারীকে "Order Placed" দেখাতে হয়তো ৮–১০ সেকেন্ড লেগে যাবে। আবার যদি ইমেইল সার্ভিস হঠাৎ ডাউন হয়, পুরো অর্ডারটাই fail হয়ে যাবে — অথচ ইমেইল তো গৌণ ব্যাপার!
আরেকটা সমস্যা — ঈদের সেলে হঠাৎ এক সেকেন্ডে ১০,০০০ অর্ডার এলে তোমার ইমেইল/SMS সার্ভিস সেই চাপ সামলাতে পারবে না। দরকার এমন একটা ব্যবস্থা যা কাজগুলো জমিয়ে রাখবে এবং সার্ভিসগুলো তাদের নিজের গতিতে কাজ করবে। এটাই Message Queue।
মূল ধারণা
Message Queue হলো একটা মধ্যস্থ ব্যবস্থা (broker), যেখানে একপক্ষ (producer) message জমা দেয় এবং আরেকপক্ষ (consumer) সেই message তুলে নিয়ে পরে process করে — দুই পক্ষ সরাসরি যুক্ত না থেকেই।
এখানে তিনটা চরিত্র:
- Producer/Consumer: যে message পাঠায় সে producer; যে তুলে নিয়ে কাজ করে সে consumer।
- Broker: মাঝখানের সফটওয়্যার (Kafka, RabbitMQ, SQS) যা message জমিয়ে রাখে ও বিলি করে।
- Queue/Topic: যেখানে message লাইন ধরে অপেক্ষা করে।
মূল লাভ — decoupling। Producer শুধু message ফেলে দিয়ে দ্রুত ব্যবহারকারীকে "Done" বলে দেয়; বাকি কাজ consumer পরে করে। এটাই async প্রক্রিয়া।
কীভাবে কাজ করে
ধাপে ধাপে
- ব্যবহারকারী অর্ডার দেয়। অ্যাপ সার্ভার শুধু একটা message ("Order #5012 created") queue-তে ফেলে দেয়।
- ব্যবহারকারী সাথে সাথেই "Order Placed" দেখে — দ্রুত।
- ইমেইল-consumer queue থেকে message তুলে ইমেইল পাঠায়।
- ইনভেন্টরি-consumer একই বা আলাদা topic থেকে নিয়ে stock কমায়।
- কোনো consumer ডাউন থাকলে message queue-তে নিরাপদে অপেক্ষা করে; সার্ভিস ফিরলে আবার process হয়।
Acknowledgement
Consumer message process করার পর broker-কে একটা ack (acknowledgement) পাঠায়, মানে "কাজ শেষ, এটা মুছে দাও"। ack না পেলে broker ধরে নেয় কাজ হয়নি, তাই message আবার ডেলিভার করে। এই ব্যবস্থার ওপরই নির্ভর করে delivery guarantee।
Delivery Guarantee
| গ্যারান্টি | মানে | ঝুঁকি |
|---|---|---|
| At-most-once | বড়জোর একবার | message হারাতে পারে |
| At-least-once | অন্তত একবার | duplicate আসতে পারে |
| Exactly-once | ঠিক একবার | বাস্তবায়ন কঠিন ও ব্যয়বহুল |
বাস্তবে বেশিরভাগ সিস্টেম at-least-once ব্যবহার করে এবং consumer-কে idempotent বানায় — মানে একই message দুবার এলেও ফলাফল একই থাকে (যেমন "Order #5012-এর ইমেইল কি পাঠানো হয়েছে?" চেক করে নেওয়া)।
ভাবো ঢাকার একটা ব্যস্ত বিরিয়ানির দোকান। ক্যাশ কাউন্টারে (producer) তুমি অর্ডার দিয়ে একটা টোকেন স্লিপ রান্নাঘরের হুকে ঝুলিয়ে দাও (queue)। বাবুর্চিরা (consumer) একটা একটা করে স্লিপ নামিয়ে রান্না করে। ক্যাশিয়ারকে রান্না শেষ হওয়ার জন্য দাঁড়িয়ে থাকতে হয় না — সে পরের কাস্টমার নেয়। ভিড় বাড়লে স্লিপ জমতে থাকে, কিন্তু কিছুই হারায় না। বাবুর্চি একটা স্লিপ ভুলে দুবার রান্না না করে — এটাই idempotency।
কৌশল
১. Point-to-Point (Queue)
একটা message লাইনে অনেক consumer থাকতে পারে, কিন্তু প্রতিটা message ঠিক একজন consumer পায়। কাজ ভাগাভাগি (load balancing) করতে আদর্শ — যেমন ১০টা worker মিলে অর্ডার process করছে, প্রতিটা অর্ডার একজনই নেবে।
২. Publish/Subscribe (Topic)
এখানে একটা message সব subscriber-এর কাছে যায়। "নতুন অর্ডার এসেছে" — এই একটা ইভেন্ট একসাথে ইমেইল-সার্ভিস, অ্যানালিটিক্স-সার্ভিস, এবং ইনভেন্টরি-সার্ভিস সবাই পায়। একই ঘটনায় একাধিক স্বাধীন প্রতিক্রিয়া দরকার হলে এটা ব্যবহার করো।
| বৈশিষ্ট্য | Point-to-Point | Pub/Sub |
|---|---|---|
| একটি message পায় | একজন consumer | সব subscriber |
| উদ্দেশ্য | কাজ ভাগ করা | একই ইভেন্ট ছড়ানো |
| উদাহরণ | অর্ডার processing | ইভেন্ট broadcasting |
৩. Backpressure
Producer যদি consumer-এর চেয়ে অনেক দ্রুত message বানায়, queue ফুলে যেতে থাকে। Backpressure হলো সেই কৌশল যেখানে সিস্টেম producer-কে গতি কমাতে বলে বা request প্রত্যাখ্যান করে, যাতে memory শেষ না হয়ে যায়।
৪. Dead-Letter Queue (DLQ)
কোনো message যদি বারবার চেষ্টা করেও (যেমন ৫ বার) process করা না যায় (corrupt data, বাগ), সেটাকে মূল queue থেকে সরিয়ে একটা আলাদা Dead-Letter Queue-তে পাঠানো হয়। এতে একটা খারাপ message পুরো লাইন আটকে রাখে না, আর তুমি পরে DLQ দেখে সমস্যা ঠিক করতে পারো।
কখন ব্যবহার করবে / করবে না
করবে:
- ধীরগতির বা গৌণ কাজকে async করতে (ইমেইল, রিপোর্ট জেনারেশন, ভিডিও এনকোডিং)।
- ট্রাফিকের হঠাৎ স্পাইক বাফার করতে।
- সার্ভিসগুলোকে আলাদা ও স্বাধীন রাখতে (microservices)।
করবে না (বা সাবধানে):
- যখন ব্যবহারকারীর সাথে সাথে ফলাফল লাগবে (synchronous, যেমন পাসওয়ার্ড যাচাই)।
At-least-once delivery মানে duplicate message আসবেই — এটা ব্যতিক্রম নয়, নিয়ম। তোমার consumer যদি idempotent না হয়, তাহলে একই অর্ডারে দুবার টাকা কাটা বা দুটো ইমেইল যাওয়া অবধারিত। প্রতিটা message-এ একটা unique ID রেখে "এটা কি আগে process করেছি?" চেক করার অভ্যাস করো।
বাস্তব উদাহরণ
Uber তাদের রিয়েল-টাইম সিস্টেমে Apache Kafka ব্যবহার করে — প্রতিদিন কয়েক ট্রিলিয়ন message। চালক ও যাত্রীর লোকেশন, ট্রিপ ইভেন্ট, ভাড়ার হিসাব — সব Kafka topic-এর মধ্য দিয়ে যায়, আর বহু আলাদা সার্ভিস সেই একই স্ট্রিম থেকে নিজের দরকারমতো পড়ে নেয়। এটা ক্লাসিক pub/sub।
আবার ছোট-মাঝারি অ্যাপে RabbitMQ (ঐতিহ্যবাহী queue, জটিল routing) আর AWS-এ SQS (ম্যানেজড, সহজ) খুব জনপ্রিয়। Kafka high-throughput ও event streaming-এ সেরা, RabbitMQ নমনীয় routing-এ, আর SQS-এ অপারেশনের ঝামেলা নেই।
ইন্টারভিউতে message queue আনলে অবশ্যই উল্লেখ করো — কোন delivery guarantee নিচ্ছ এবং consumer কীভাবে idempotent বানাচ্ছ। সাথে DLQ আর backpressure-এর কথা বললে দেখা যায় তুমি শুধু "queue ব্যবহার করব" বলে থেমে যাওনি, বরং বাস্তব ব্যর্থতার ক্ষেত্রগুলোও ভেবেছ — এটাই senior চিন্তা।
মূল শব্দ (Key Terms)
মিনি কুইজ
1. Message Queue ব্যবহারের মূল সুবিধা কোনটি?
2. At-least-once delivery মানে কী?
3. Dead-Letter Queue (DLQ) কীসের জন্য?