আমি পূর্বে Design a Highly Concurrent Wordcamp Event Booking System লিখেছিলাম। যা আমাদেরকে ধারণা দিয়েছে,
Exclusive Lock কি?
কেনো Concurrency হ্যান্ডলিং শুধু FOR UPDATE দিলেই শেষ নয়
Deadlock কখন হয়?
ATOMIC সিট বুকিং
কিভাবে retry করবো?
কেনো Transaction? সাধারণ আপডেট (UPDATE) কোয়েরি তে সমস্যা কি?
সবকিছু ঠিক আছে। একটি বিষয় ছাড়া, তা হচ্ছে পারফরমেন্স। আমরা এরকম ভাবতে পারি,
১০,০০০ মানুষ কিছু মিলিসেকেন্ড অন্তর “Book” বাটন এ ক্লিক করেছে। এতে ডাটাবেস এ একসাথে (বলা যায়) ১০,০০০ টি রিকোয়েস্ট চলে গেলো।
ডাটাবেস storage এরকম হাজার হাজার রিকোয়েস্ট হ্যান্ডেল করার জন্য তৈরী(optimized) করা হয় নি, বরং তা মূলত Storage এবং Query করে ডেটা আনার জন্য তৈরী করা হয়েছে।
Locking mechanism থাকার পরেও এতো এতো রিকোয়েস্ট হ্যান্ডেল করতে গেলে তখন Latency খুব বাড়তে থাকবে।
তাহলে আমরা কি করতে পারি?
উত্তর হচ্ছে, Redis এবং Kafka ব্যবহার করতে পারি।
Redis শুধু ক্যাশিং এর জন্য নয়। আমাদের এখানে, Redis কে আমরা First-Come-First-Serve এর জন্য ব্যবহার করতে পারবো। এবং Kafka একটি নির্দিষ্ট পার্টিশন এর ভিতর ordering নিশ্চিত করে থাকে, সাথে Durability নিশ্চিত করে। এই ২টি(Redis এবং Kafka) ব্যবহার করে আমরা Latency সংক্ষিপ্ত করতে পারবো।
প্রসেসটি শুরু করা যাক,
ইনকামিং রিকোয়েস্টগুলো প্রথমে Redis Stream এ লিখা হবে। Redis রিকোয়েস্টগুলো গ্রহণ করার সঙ্গে সঙ্গেই (in-memory, ~sub-millisecond) acknowledgment পাঠায়। আমরা তখন user কে “successfully booked” মেসেজ পাঠিয়ে দিতে পারি, অর্থাৎ FAST RESPONSE।
তারপর আমরা redis এর একটি কাউন্টার + timestamps ব্যবহার করে, প্রতিটা রিকোয়েস্টকে count করে রাখতে পারি। এতে কি সুবিধা হবে? ২টি রিকোয়েস্ট কখনো নিজেদের মধ্যে একই order হবে না।
তারপর redis সকল রিকোয়েস্টগুলো একসাথে batch করে, একটি নির্দিষ্ট Kafka পার্টিশন এ পাঠিয়ে দিবে।
পার্টিশনের ভিতর প্রতিটা রিকোয়েস্ট অর্ডার মেইনটেইন করে queue তে থাকবে।
booking সার্ভিস kafka পার্টিশন থেকে রিকোয়েস্ট নিবে, তারপর ডাটাবেস সেই রিকোয়েস্ট কে নিয়ে Exclusive Lock তৈরী করবে এবং বুকিং রেকর্ড ডাটাবেস এ আপডেট হবে।
যেহেতু আমরা প্রথম স্টেপ এ রেসপন্স পাঠিয়ে দিচ্ছি(যদিও step 4 ডাটাবেস booking আপডেট করা হচ্ছে), সেহেতু performance খুবই ভালো হবে। এবং kafka durability জন্য আমাদের কোনো রিকোয়েস্ট নষ্ট হবে না, যার ফলে consistency বজায় থাকবে।
একটি বিষয় আমাদেরকে মনে রাখতে হবে যে kafka নির্দিষ্ট পার্টিশনে অর্ডার বজায় রাখে, তার মানে আমরা চাইলে redis নাও ব্যবহার করতে পারি যদি পার্টিশন নম্বর জানা থাকে।