Double booking ছাড়া ticket booking সিস্টেম ডিজাইন

একই সিট দুজন কিনতে পারবে না। Booking সিস্টেমের জন্য seat hold, locking ও payment timeout ডিজাইন করি।

একটি সিট hold অবস্থায় থাকা seat map

লক্ষ্য: user শো বা ফ্লাইটের সিট বাছে, অল্প সময় hold করে রাখে, টাকা দেয় ও টিকিট পায়। একটি সিট সর্বোচ্চ একবার বিক্রি হয়।

Requirement

  • ইভেন্ট দেখা ও কোন সিট ফাঁকা তা জানা।
  • সিট বাছা এবং payment-এর সময় (যেমন ১০ মিনিট) সেগুলো hold রাখা।
  • হাজারো মানুষ একসাথে ক্লিক করলেও একটি সিট দুবার বিক্রি হবে না।
  • Payment ব্যর্থ বা সময় শেষ হলে সিট ছেড়ে দেওয়া।

কঠিন অংশ: contention

জনপ্রিয় ইভেন্টে অনেকে একই মুহূর্তে একই সিট চায়। সঠিকতা সবার আগে, তাই সিটের অবস্থা atomic ভাবে বদলাতে হবে।

সিটের অবস্থা

AVAILABLE -> HELD (সময় T পর্যন্ত) -> SOLD, আর hold-এর মেয়াদ শেষ বা payment ব্যর্থ হলে HELD -> AVAILABLE।

Double booking ঠেকানো

একটি নিরাপদ পদ্ধতি বাছুন:

  • Conditional update: UPDATE seats SET status='HELD', held_by=?, hold_until=? WHERE seat_id=? AND (status='AVAILABLE' OR hold_until < now())। এক row বদলালে সিট পেয়েছেন। শূন্য হলে অন্য কেউ পেয়েছে। এক statement-এই সহজ ও সঠিক।
  • Optimistic locking: version column রাখুন এবং version মিললে তবেই আপডেট করুন।
  • Row lock (SELECT ... FOR UPDATE): নিরাপদ, কিন্তু lock বেশিক্ষণ ধরে।
  • Hold-এর জন্য Redis SET key NX EX, আর database চূড়ান্ত সত্যের উৎস।

tickets table-এ (event_id, seat_id)-র unique constraint শেষ নিরাপত্তা জাল।

Booking প্রবাহ

  1. User সিট বাছে। Server সবগুলো এক transaction-এ hold করতে চেষ্টা করে (সব, নয়তো কিছুই না)।
  2. User hold-এর সময়ের মধ্যে টাকা দেয়।
  3. Payment সফল: সিট SOLD করে টিকিট তৈরি। এই ধাপ idempotent, তাই retry হওয়া callback দুবার কিছু করে না।
  4. ব্যর্থতা বা timeout: background job (বা lazy মেয়াদ যাচাই) সিট ছেড়ে দেয়।

Payment race

Hold-এর মেয়াদ শেষের ঠিক পরে payment সফল হতে পারে। সফল হলে একই transaction-এ hold আবার যাচাই করুন। সিট চলে গেলে স্বয়ংক্রিয় refund দিন ও user-কে জানান।

ভিড় সামলানো

  • Virtual waiting room: user-দের ভাগে ভাগে ঢোকান যাতে booking পথ ডুবে না যায়।
  • সিট মানচিত্র cache থেকে দিন, আর hold-এর সময় উপলব্ধতা যাচাই করুন।
  • Rate limit দিন ও bot আটকান।
  • Read অনায়াসে scale করুন, কিন্তু সিট table-এ write পথ ছোট ও দ্রুত রাখুন।

Scaling

ইভেন্ট অনুযায়ী shard করুন, কারণ আলাদা ইভেন্টের সিট একে অপরকে প্রভাবিত করে না। একমাত্র সমস্যা গরম ইভেন্ট, যা waiting room আর দ্রুত conditional update সামলায়।

মূল কথা: সিট hold-এ atomic conditional update, hold-এর মেয়াদ স্বয়ংক্রিয়ভাবে শেষ করুন, payment নিশ্চিতকরণ idempotent রাখুন, আর waiting room দিয়ে সিস্টেম বাঁচান।


System Design সিরিজ, পর্ব ৩ (case study): 11 নম্বর (মোট 16)। আগের লেখা: Google Drive-এর মতো file storage ও sync ডিজাইন.

আরও পড়ুন

Recursion ও backtracking সহজ উদাহরণে

Recursion সমস্যার ছোট কপি সমাধান করে সমাধান করে। অনেক interview সমস্যায় ব্যবহৃত চিন্তার ধাপ ও backtracking টেমপ্লেট শিখুন।

Interview ও DSA•৩ মিনিটে পড়া