সরাসরি পর্বে যান
পর্ব ০১ · ৬৬-এর মধ্যে · মডিউল ১

System design কী — একটি অ্যাপ থেকে কোটি ব্যবহারকারীর সিস্টেম

What Is System Design — From One Server to Millions of Users

Taught in Bangla, this lesson defines system design as the blueprint of a whole service and separates high-level from low-level design. It follows one app growing from a single server through load balancers, caches, read replicas, CDN, queues, sharding and multiple regions, converts DAU into QPS, budgets the latency of one request, spots single points of failure, surveys the building blocks and trade-offs, and maps the course, with runnable calculators and step-by-step diagrams.

এই পর্বে যা শিখবেন

  • System design কী, আর high-level ও low-level design-এর পার্থক্য কোথায়
  • একটি অ্যাপ একটি সার্ভার থেকে কোটি ব্যবহারকারী পর্যন্ত কোন কোন ধাপে বড় হয়, আর প্রতিটি ধাপ কোন সমস্যার সমাধান
  • DAU থেকে QPS, একটি অনুরোধের latency-র বাজেট আর cache-এর লাভ — সংখ্যা দিয়ে হিসাব
  • Single point of failure চেনা, প্রধান building block-গুলোর ভূমিকা আর trade-off-এর চিন্তা
  • কোর্সের ১০টি মডিউলের মানচিত্র, পূর্বপ্রস্তুতি, আর AI দিয়ে নকশা করার সময় কী যাচাই করবেন

১ · System design কী — পুরো সেবার নকশা

ফোনে mobile banking, ride-sharing, খাবার অর্ডার বা ভিডিওর অ্যাপ খুলে কখনো ভেবেছেন — একই মুহূর্তে লাখো মানুষ বোতাম চাপছেন, তবু প্রত্যেকে এক সেকেন্ডের কম সময়ে উত্তর পাচ্ছেন কীভাবে? কোনো একটি সার্ভার নষ্ট হলেও অ্যাপ চলছে কীভাবে? এর উত্তর কোনো একটি চতুর প্রোগ্রামে নেই। উত্তর আছে পুরো ব্যবস্থার নকশায় — কয়টি সার্ভার, ডেটা কোথায়, কোন অনুরোধ কোন পথে যায়, আর কোনো অংশ বিকল হলে কে দায়িত্ব নেয়। এই নকশার নামই system design.

মূল ধারণা

System design হলো একটি সফটওয়্যার সেবার উপাদানগুলো (client, সার্ভার, database, cache, queue…), তাদের মধ্যকার সংযোগ ও API, আর ডেটার পথ এমনভাবে ঠিক করা, যাতে সেবাটি তার প্রয়োজন মেটায় — নির্দিষ্টসংখ্যক ব্যবহারকারী, নির্দিষ্ট গতি, কোনো অংশ বিকল হলেও চালু থাকা, আর সাধ্যের মধ্যে খরচ।

একটি বড় রেস্তোরাঁর কথা ভাবুন। মালিককে ঠিক করতে হয়: কয়টি রান্নাঘর, ওয়েটার অর্ডারের স্লিপ কোথায় রাখবেন, ভাঁড়ার ঘর কোথায়, ভিড় বাড়লে দ্বিতীয় শাখা কোথায়, গ্যাসের লাইন বন্ধ হলে বিকল্প কী। এটি পুরো ব্যবস্থার নকশা — high-level design. আবার একজন বাবুর্চি নিজের চুলার পাশে মসলা কোন ক্রমে সাজাবেন, বিরিয়ানির রেসিপির ধাপগুলো কী — এটি একটি অংশের ভেতরের নকশা, low-level design. দুটোই দরকার, কিন্তু প্রশ্ন আলাদা, দক্ষতাও আলাদা।

দিকHigh-level design (HLD)Low-level design (LLD)
মূল প্রশ্নকোন কোন উপাদান, কীভাবে যুক্ত, কোন ডেটা কোথায়একটি সার্ভিস বা প্রোগ্রামের ভেতরে কোন class, interface, ফাংশন
নকশার এককসার্ভার, database, cache, queue, networkclass, object, method, design pattern
যা মাপা হয়scale, latency, availability, consistency, খরচপড়ার সহজতা, পুনর্ব্যবহার, test করার সহজতা
যা তৈরি হয়architecture diagram, API, data model, ক্ষমতার হিসাবclass diagram, sequence diagram, কোড
উদাহরণ: ride-sharingচালকের location কোন সার্ভিসে যায়, কোন database-এ থাকে, কতবার আসে; যাত্রী-চালকের মিল কোথায় হয়Ride, Driver, FareCalculator class; ভাড়ার নিয়ম আলাদা strategy হিসেবে
কোথায় শিখবেনএই কোর্সJava · design pattern, C++ · SOLID

এই কোর্স মূলত HLD নিয়ে। তবে সীমারেখা পুরো স্পষ্ট নয়: API-র রূপ (পর্ব ৮) বা টেবিল আর index-এর নকশা (পর্ব ২১) দুই জগতেরই অংশ, আর আমরা এগুলোও দেখব। নামও জায়গাভেদে আলাদা — কোথাও “architecture”, কোথাও “system design”; ইন্টারভিউতে LLD-কে কখনো “object-oriented design” বলা হয়।

২ · কেন দরকার — পাঁচটি চাপ

একটি সার্ভারে চলা ছোট অ্যাপ আর কোটি মানুষের অ্যাপের মূল কোড হয়তো প্রায় একই; পার্থক্য পরিবেশে। ব্যবহারকারী বাড়লে পাঁচটি চাপ একসাথে আসে, আর system design এই পাঁচটির মধ্যে ভারসাম্য খোঁজে:

Scale — বাড়তি ভার

১০০ জন থেকে ১ কোটি জন: বাড়তি অনুরোধ, বাড়তি ডেটা আর ভিড় সামলানোর ক্ষমতাকে বলে scalability. শুধু গড় নয়, সবচেয়ে ব্যস্ত মুহূর্তটিও সামলাতে হয়।

কত বড় হতে পারে?

Reliability — বিকল হলেও চালু

হাজারো যন্ত্রের ভিড়ে প্রায় প্রতিদিন কোথাও না কোথাও disk বা সার্ভার নষ্ট হয়। সেবা চালু থাকার হার availability, আর ঠিকঠাক কাজ করে যাওয়ার নিশ্চয়তা reliability.

ব্যর্থতা স্বাভাবিক ঘটনা

Latency — দ্রুত উত্তর

একটি অনুরোধের উত্তর আসতে যে সময় লাগে, তা latency; আর প্রতি সেকেন্ডে কতগুলো অনুরোধ সামলানো যায়, তা throughput. ধীর অ্যাপ থেকে মানুষ সরে যান।

মিলিসেকেন্ডের হিসাব

খরচ — সাধ্যের মধ্যে

দরকারের দশ গুণ সার্ভার রাখলে টাকা নষ্ট, কম রাখলে ভিড়ে সেবা বন্ধ। Cloud-এর বিল, bandwidth আর মানুষের সময় — সবই নকশার অংশ।

প্রতি অনুরোধে কত টাকা?

বদলানোর ক্ষমতা

আজকের নকশা কাল বদলাতে হবে: নতুন ফিচার, নতুন দল, নতুন নিয়ম। সেবা বন্ধ না করে সহজে বোঝা, চালানো আর বদলানো যায় এমন গুণের নাম maintainability.

আগামী বছরের নকশা

একটি বাস্তবধর্মী দৃশ্য — পরীক্ষার ফল প্রকাশের দিন। ধরা যাক একটি ফলের সাইটে সাধারণ দিনে সারা দিনে ৫০ হাজার অনুরোধ আসে, গড়ে সেকেন্ডে একটিরও কম (প্রায় ০.৬)। ফল প্রকাশের প্রথম ১০ মিনিটে ১০ লাখ মানুষ গড়ে ৫টি করে অনুরোধ পাঠালে আসে সেকেন্ডে প্রায় ৮,৩৩৩টি — সাধারণ গড়ের ১৪,৪০০ গুণ! এমন দিনে সাইট খুলতে না চাওয়ার কারণ প্রায়ই প্রোগ্রামের ভুল নয়; নকশাটি গড়ের জন্য করা, সবচেয়ে ব্যস্ত মুহূর্তের জন্য নয়। ঈদের আগে বাসের অনলাইন টিকিটেও একই গল্প।

মূল ধারণা

System design-এর প্রায় প্রতিটি প্রশ্ন এই পাঁচ চাপের কোনো একটি বা কয়েকটির উত্তর। আর পাঁচটিকে একসাথে সর্বোচ্চ করা যায় না — একটি বাড়াতে গেলে আরেকটির দাম দিতে হয়। এই দর-কষাকষির কথা অংশ ৮-এ, আর প্রয়োজনগুলো কীভাবে লিখতে হয় তা পর্ব ০২-এ।

৩ · মহল্লার দোকান থেকে দেশজোড়া চেইন — একটি অ্যাপের বেড়ে ওঠা

এবার পুরো কোর্সের মানচিত্রটি একটি গল্পে দেখা যাক। একটি কাল্পনিক অনলাইন বাজারের অ্যাপ — চাল, ডাল, তেল অর্ডার করা যায় — শুরু করলেন দুই বন্ধু। পাশাপাশি চলবে আরেকটি গল্প: রহিম সাহেবের মহল্লার মুদি দোকান, যা ধীরে ধীরে গুদাম আর ডিপোসহ দেশজোড়া চেইন হয়ে উঠল। প্রতিটি ধাপে দুটি প্রশ্ন খেয়াল করুন: কোন সমস্যা এই বদল বাধ্য করল? আর বদলের দাম কী?

নিচের ছবিতে প্রতিটি ধাপের architecture; লাল ড্যাশ দাগে ঘেরা অংশটি সেই ধাপে নতুন। “পরে” চাপুন, অথবা “চালান” চাপলে নিজে থেকেই এগোবে।

একটি অ্যাপের architecture, ধাপে ধাপে একটি সার্ভার থেকে load balancer, cache, replica, CDN, queue, shard আর দ্বিতীয় region পর্যন্ত ধাপে ধাপে বেড়ে ওঠা architecture; লাল ড্যাশ দাগে ঘেরা অংশটি সেই ধাপে নতুন। Region ১ ব্যবহারকারী ফোন · ব্রাউজার CDN ছবি · JS · CSS DNS region বাছাই Load balancer একটি সার্ভার App + Database একসাথেশুরুতে এটুকুই যথেষ্ট — বাকি সব পরে, দরকার হলে App সার্ভার App ১ stateless App ২ stateless App ৩ stateless Cache গরম ডেটা মেমরিতে Queue → Worker ধীর কাজ পরে Databaseএকটি সার্ভার Replicaশুধু পড়াPrimaryলেখা + পড়াReplicaশুধু পড়াprimary থেকে কপি (async) Shard AShard Bprimaryreplicaprimaryreplica ডেটা replication Region ২ — একই সেটআপের কপি
এই ধাপে
চাপ
সমাধান
বিস্তারিত
  1. ধাপ ১ — একটি সার্ভারেই সব। রহিম সাহেব নিজেই বিক্রি করেন, পেছনের ঘরেই মাল আর হিসাবের খাতা। আমাদের অ্যাপের শুরুও এমন: একটি ভাড়া করা সার্ভারে app প্রোগ্রাম আর database একসাথে — কয়েক হাজার ব্যবহারকারীর জন্য সস্তা, সহজ আর যথেষ্ট। ভিড় বাড়লে প্রথম চেষ্টা সাধারণত বড় মেশিন (বেশি CPU, RAM); একে বলে vertical scaling. সহজ, কিন্তু এর ছাদ আছে, আর মেশিন একটিই থেকে যায়।
  2. ধাপ ২ — database আলাদা সার্ভারে। দোকান আর গুদাম এক ঘরে থাকলে ভিড়ে ক্রেতা আর মাল দুটোই আটকায়; তাই মাল গেল পাশের গুদামে। তেমনি app আর database একই CPU, RAM আর disk নিয়ে টানাটানি করে। আলাদা করলে দুটোকে আলাদাভাবে বড় করা যায়, database-এর দ্রুত disk আর backup সামলানো সহজ হয়, আর app সার্ভার নতুন করে বানালেও ডেটা হারায় না।
  3. ধাপ ৩ — load balancer আর কয়েকটি stateless app সার্ভার। ঈদের আগে ভিড়, একজন বিক্রেতা আর পারছেন না। নতুন কাউন্টার খুলল, আর দরজায় একজন টোকেন দিয়ে প্রত্যেককে খালি কাউন্টারে পাঠান — ব্যাংকের টোকেন-ব্যবস্থার মতো। এটাই load balancer. শর্ত: কোনো কাউন্টার নিজের আলাদা খাতা রাখবে না, সব হিসাব থাকবে এক জায়গায়; তাহলে যেকোনো কাউন্টার যেকোনো ক্রেতাকে সেবা দিতে পারে। App সার্ভারের এই গুণের নাম stateless. যন্ত্র বাড়িয়ে ক্ষমতা বাড়ানোকে বলে horizontal scaling; একটি সার্ভার নষ্ট হলেও বাকিরা চালিয়ে যায়।
  4. ধাপ ৪ — cache. চাল-ডাল-তেল-চিনি বারবার বিক্রি হয়, প্রতিবার গুদামে যাওয়া সময়ের অপচয়; তাই এগুলো রাখা হলো সামনের তাকে। Database-এর সামনে cache ঠিক এই তাক: বারবার চাওয়া ডেটা মেমরিতে থাকে, উত্তর আসে প্রায় এক মিলিসেকেন্ডে, আর database-এর ভার নাটকীয়ভাবে কমে। দাম: তাকের মাল গুদামের চেয়ে পুরোনো হতে পারে — কখন বাতিল হবে, তা ঠিক করতে হয়।
  5. ধাপ ৫ — read replica. Cache-এ যা থাকে না — খোঁজা, পুরোনো অর্ডার, রিপোর্ট — সেই পড়াও এখন এক database-এর জন্য বেশি। সমাধান: database-এর কয়েকটি কপি, অর্থাৎ read replica রাখা। সব লেখা যায় primary-তে, সে পরিবর্তনগুলো কপিতে পাঠায় (replication), আর পড়ার কাজ ভাগ হয় সবার মধ্যে — যেমন মূল খাতা থেকে প্রতিটি কাউন্টারে দামের তালিকার ফটোকপি। দাম: কপিতে পৌঁছাতে সামান্য দেরি (replication lag), তাই সদ্য দেওয়া অর্ডার কপিতে এক মুহূর্ত পরে দেখা দিতে পারে।
  6. ধাপ ৬ — CDN. সিলেট বা রাজশাহীর ক্রেতাকে প্রতিটি ছবি আর JavaScript ফাইল দূরের data centre থেকে আনতে হচ্ছে — ধীর, খরচও বেশি। প্যাকেটের মাল যেমন জেলায় জেলায় ডিপোতে থাকে, তেমনি CDN স্থির ফাইলের (ছবি, CSS, JavaScript, ভিডিও) কপি রাখে ব্যবহারকারীর কাছের সার্ভারে।
  7. ধাপ ৭ — message queue. অর্ডার দিলেই অনেক কাজ: invoice-এর PDF, SMS, ইমেইল, গুদামের হিসাব। সব একসাথে করলে ক্রেতা কয়েক সেকেন্ড ঘুরন্ত চাকা দেখেন, আর SMS-সেবা ধীর হলে অর্ডারই আটকায়। ওয়েটার যেমন অর্ডারের স্লিপ রান্নাঘরের লাইনে রেখে আসেন, তেমনি app কাজগুলো একটি message queue-তে রেখে সঙ্গে সঙ্গে বলে, “অর্ডার পেয়েছি।” পেছনে worker নিজের গতিতে কাজগুলো সারে।
  8. ধাপ ৮ — sharding. এবার লেখার চাপই একটি primary-র সাধ্যের বাইরে, ডেটাও এক মেশিনের disk-এ আঁটে না। Replica কাজে আসে না, কারণ প্রতিটি লেখা সব কপিতেই যায়। সমাধান ডেটা ভাগ করা — যেমন উত্তর আর দক্ষিণ ঢাকার আলাদা গুদাম, আলাদা খাতা। এর নাম sharding: প্রতিটি shard ডেটার একটি অংশের মালিক, সাধারণত গ্রাহকের id দেখে ঠিক হয় কে কোথায়। দাম: একাধিক shard জুড়ে join বা transaction কঠিন।
  9. ধাপ ৯ — একাধিক region. পুরো একটি data centre-ও বসে যেতে পারে — বিদ্যুৎ বিভ্রাট, বন্যা, fiber কাটা। বড় চেইন যেমন দ্বিতীয় শহরে কেন্দ্রীয় গুদাম রাখে, তেমনি পুরো ব্যবস্থার একটি কপি চলে দূরের আরেকটি region-এ; ডেটা সেখানে কপি হয়, আর DNS ব্যবহারকারীকে সুস্থ region-এ পাঠায়। সবচেয়ে দামি আর জটিল ধাপ: কপিতে দেরি থাকে, আর দুই region-এর কার লেখা চূড়ান্ত, সেই কঠিন প্রশ্ন আসে (পর্ব ৪০, ৫১)।

এই গল্প বানানো নয়। ১৯৯০-এর দশকের শেষে অগণিত ওয়েবসাইট একটি সার্ভারে Linux, Apache, MySQL আর PHP একসাথে চালাত; ১৯৯৮ সালে জার্মান কম্পিউটার-পত্রিকা c't-এর একটি লেখায় Michael Kunze এই চারটির একসাথে নাম দেন LAMP. ২০০৩ সালে ব্লগ-সাইট LiveJournal-এর database-এর ভার কমাতে Brad Fitzpatrick লেখেন memcached নামের একটি cache, যা পরে বহু বড় সাইটে ছড়িয়ে পড়ে। ২০১৩ সালে NSDI সম্মেলনে Facebook-এর প্রকৌশলীদের গবেষণাপত্র “Scaling Memcache at Facebook” দেখায়, সেই একই ধারণা কীভাবে বিশাল আকারে চালানো হয়। ধাপগুলোর নাম আজও একই।

এক নজরে — কোন চাপে কোন ধাপ

ধাপযে সমস্যা বদল বাধ্য করলসমাধানবিস্তারিত
১— (শুরু)একটি সার্ভার; দরকারে বড় মেশিনপর্ব ১৩
২app আর DB-র টানাটানি, backupDB আলাদা সার্ভারেপর্ব ১৩, ১৯–২০
৩এক app সার্ভারের সীমা, একক বিকল-বিন্দুload balancer + stateless appপর্ব ১৩–১৫
৪একই ডেটা বারবার পড়াcacheপর্ব ২৮–৩০
৫পড়ার চাপ তবুও বেশিread replicaপর্ব ২২
৬দূরের ব্যবহারকারী, bandwidthCDNপর্ব ১৭, ২৬
৭ধীর কাজে ব্যবহারকারীর অপেক্ষাqueue + workerপর্ব ৩১, ৩৪, ৩৭
৮লেখার চাপ আর ডেটার আকারshardingপর্ব ১৬, ২৩
৯পুরো data centre বিকলবহু regionপর্ব ৪০, ৫১

গল্পের ক্রমটি শেখার সুবিধার জন্য, আইন নয়। ভিডিওর অ্যাপ প্রথম দিন থেকেই CDN নেয়; টাকা-লেনদেনের সেবা শুরু থেকেই database-এর কপি রাখে। আবার অনেক সফল সেবা বছরের পর বছর ধাপ ৩–৫-এই থাকে। নিয়ম একটাই: আগে সমস্যা মাপুন, তারপর সমাধান আনুন। প্রতিটি নতুন বাক্স মানে নতুন খরচ আর ব্যর্থতার নতুন পথ।

৪ · কত ব্যবহারকারীতে কোন ধাপ — DAU থেকে QPS

“কত ব্যবহারকারী” প্রশ্নটিকে সার্ভারের ভাষায় বদলাতে হয়: প্রতি সেকেন্ডে কতগুলো অনুরোধ, অর্থাৎ QPS (queries per second; ওয়েবে একে requests per second-ও বলা হয়)। হিসাব শুরু হয় DAU (daily active users — দিনে অন্তত একবার আসা ব্যবহারকারী) থেকে:

গড় QPS = DAU × প্রতি জনের দৈনিক অনুরোধ ÷ 86,400
peak QPS = গড় QPS × peak factor

৮৬,৪০০ হলো এক দিনের সেকেন্ড (২৪ × ৬০ × ৬০)। কিন্তু মানুষ সারা দিন সমানভাবে আসেন না — সন্ধ্যায় ভিড়, রাত তিনটায় ফাঁকা। তাই সবচেয়ে ব্যস্ত সময়ের ভার গড়ের কয়েক গুণ ধরা হয়; এই গুণককে আমরা বলব peak factor. এ ধরনের মোটা দাগের দ্রুত হিসাবকে বলে back-of-the-envelope হিসাব — খামের পেছনেই কষে ফেলা যায় এমন অঙ্ক। পুরো কৌশল পর্ব ০৩-এ।

নিচের ক্যালকুলেটর DAU ১ হাজার থেকে ১০ কোটি পর্যন্ত, প্রতি ধাপে ১০ গুণ করে, হিসাব করে কোন architecture ধাপ লাগতে পারে। সব ক্ষমতা ধরে নেওয়া গোল সংখ্যা — যেমন প্রতি জন দিনে ৪০টি অনুরোধ, peak factor ৩, একটি app সার্ভার সেকেন্ডে ~৫০০ অনুরোধ, একটি database ~৫,০০০ query; বাকিগুলো কোডের মন্তব্যে। বাস্তবে কাজের ধরন অনুযায়ী এগুলো দশ গুণ এদিক-ওদিক হতে পারে।

// Growth-stage calculator. Every capacity below is an ASSUMPTION (a round
// number for teaching), not a measurement. Measure yours with a load test.
const REQ_PER_USER = 40;  // requests per daily active user per day
const PEAK = 3;           // busiest hour = 3 x the daily average
const ONE_BOX = 100;      // app + DB together on ONE machine: ~100 req/s
const APP_CAP = 500;      // one stateless app server: ~500 req/s
const DB_CAP = 5000;      // one database server: ~5,000 queries/s
const Q_PER_REQ = 2;      // database queries per request
const WRITES = 0.05;      // 5% of the queries are writes
const HIT = 0.9;          // cache hit ratio for reads, once a cache exists

function stage(peak) {
  const q = peak * Q_PER_REQ, w = q * WRITES, r = q - w;
  const afterCache = r * (1 - HIT) + w;          // DB load with a cache
  if (peak <= ONE_BOX) return "1 one server (app + DB)";
  if (peak <= APP_CAP) return "2 app server + separate DB";
  if (q <= DB_CAP) return "3 LB + stateless app servers";
  if (afterCache <= DB_CAP) return `4 + cache (DB load ${afterCache.toFixed(0)}/s)`;
  if (w <= DB_CAP) return `5 + read replicas (${Math.ceil(r * (1 - HIT) / DB_CAP)})`;
  return `8 + sharding (writes ${w.toFixed(0)}/s)`;
}

console.log("DAU          avg/s   peak/s  apps  likely stage");
for (const dau of [1e3, 1e4, 1e5, 1e6, 1e7, 1e8]) {
  const avg = dau * REQ_PER_USER / 86400, peak = avg * PEAK;
  const apps = Math.ceil(peak / APP_CAP);
  console.log(dau.toLocaleString("en-US").padEnd(12) + avg.toFixed(1).padStart(8) +
    peak.toFixed(1).padStart(9) + String(apps).padStart(6) + "  " + stage(peak));
}

আসল রানের আউটপুট:

DAU          avg/s   peak/s  apps  likely stage
1,000            0.5      1.4     1  1 one server (app + DB)
10,000           4.6     13.9     1  1 one server (app + DB)
100,000         46.3    138.9     1  2 app server + separate DB
1,000,000      463.0   1388.9     3  3 LB + stateless app servers
10,000,000    4629.6  13888.9    28  4 + cache (DB load 4028/s)
100,000,000  46296.3 138888.9   278  8 + sharding (writes 13889/s)

“likely stage” মানে সবচেয়ে উঁচু যে ধাপটি লাগবে; আগের ধাপগুলোও তার মধ্যে ধরা। ১ হাজার আর ১০ হাজার DAU-তে peak মাত্র ১.৪ আর ১৩.৯ অনুরোধ/সেকেন্ড — একটি সার্ভারই যথেষ্ট; এখানে microservices আনা মানে টাকা আর সময় নষ্ট। ১ লাখে peak ১৩৮.৯, এক বাক্সের ধরে নেওয়া সীমা ১০০ পেরোল, তাই DB আলাদা। ১০ লাখে peak ১,৩৮৮.৯ — একটি app সার্ভারের ৫০০-র প্রায় তিন গুণ, তাই load balancer আর ৩টি app সার্ভার; DB-তে তখনো ২,৭৭৮ query/s. ১ কোটিতে DB-তে যেত ২৭,৭৭৮ query/s; ৯০% hit-এর cache বসালে নামে ৪,০২৮-এ। ১০ কোটিতে শুধু লেখাই ১৩,৮৮৯/s — একটি primary-র ধরে নেওয়া ৫,০০০-এর প্রায় তিন গুণ; replica সাহায্য করে না, কারণ প্রতিটি লেখা সব কপিতে যায়। তাই sharding.

১০ গুণের লাফে ধাপ ৫ (read replica) চোখে পড়ে না; তালিকায় 3e7 যোগ করলে ৩ কোটি DAU-র সারিতে দেখবেন 5 + read replicas (2) — সরল হিসাব: প্রতিটি replica-কেও সব লেখা প্রয়োগ করতে হয়, সেই খরচ এখানে ধরা হয়নি, তাই বাস্তবে replica আরও বেশি লাগবে। আর CDN, queue বা বহু region এই টেবিলে আসেনি — এগুলো আসে QPS ছাড়া অন্য চাপে: দূরত্ব, ধীর কাজ, আর পুরো data centre বিকল হওয়ার ঝুঁকি।

এই সংখ্যাগুলো সিদ্ধান্তের শুরু, শেষ নয়। একটি app সার্ভার সত্যিই কত অনুরোধ সামলায়, তা নির্ভর করে প্রতিটি অনুরোধে কত কাজ, কোন ভাষা আর কতগুলো database call — তার ওপর। আসল সংখ্যা পেতে load test করতে হয়: পরীক্ষার পরিবেশে কৃত্রিমভাবে বাড়তি অনুরোধ পাঠিয়ে মাপা, কোথায় গিয়ে সেবা ধীর হয় বা ভেঙে পড়ে। আর ভার কম হলেও শুধু নিরাপত্তার জন্য অন্তত দুটি app সার্ভার রাখা প্রায়ই বুদ্ধিমানের কাজ (অংশ ৬)।

৫ · একটি অনুরোধের যাত্রা — সময় যায় কোথায়

সংখ্যার দ্বিতীয় দিক সময়। ব্যবহারকারী অ্যাপে একটি পণ্যের পাতা খুললেন; অনুরোধটি ফোন থেকে database পর্যন্ত গিয়ে ফেরে, আর প্রতিটি ধাপে কিছু মিলিসেকেন্ড যোগ হয়। ধরে নেওয়া মান: ফোন থেকে data centre পর্যন্ত একবার যাওয়া-আসা (RTT) ৪০ ms, cache-এ খোঁজা ১ ms, database query ২৫ ms. তথ্যটি cache-এ নেই (miss) — সবচেয়ে লম্বা পথ।

  1. ফোন + DNSapi.example.comনাম থেকে ঠিকানা
  2. Load balancerTCP + TLSসংযোগ এখানে
  3. App সার্ভারGET /products/42ব্যবসার নিয়ম
  4. CacheMISSমেমরিতে খোঁজা
  5. DatabaseSELECT …মূল কপি
সময়ের খাতা
এই ধাপে
যোগ হলো
মোট সময়
  1. ধাপ ১ — নাম থেকে ঠিকানা। অ্যাপ জানে সার্ভারের নাম api.example.com, কিন্তু যোগাযোগ চলে IP ঠিকানায়। ফোন DNS resolver-কে জিজ্ঞেস করে — ধরা যাক ২০ ms. উত্তরটি কিছুক্ষণ জমা থাকে, তাই পরের অনুরোধে এই খরচ প্রায় শূন্য।
  2. ধাপ ২ — হাত মেলানো: TCP আর TLS. ডেটা পাঠানোর আগে ফোন আর load balancer একটি সংযোগ খোলে (TCP, ১ RTT), তারপর গোপন চাবিতে একমত হয় (TLS 1.3, আরও ১ RTT). RTT ৪০ ms ধরলে এখানেই ৮০ ms, মোট ১০০ ms — অথচ আসল প্রশ্নটি এখনো পাঠানোই হয়নি।
  3. ধাপ ৩ — load balancer. অনুরোধটি ফোন থেকে load balancer-এ পৌঁছাতে লাগে অর্ধেক RTT, ২০ ms. কোন app সার্ভারগুলো সুস্থ, LB তা জানে; সে একটিকে বেছে দেয় প্রায় ১ ms-এ। মোট ১২১ ms.
  4. ধাপ ৪ — app সার্ভার আর cache. App সার্ভার অনুরোধ যাচাই করে, ব্যবসার নিয়ম চালায় (১০ ms), তারপর cache-এ খোঁজে “পণ্য ৪২” আছে কি না — ১ ms পরে উত্তর এলো MISS, অর্থাৎ নেই। একই data centre-এর ভেতরে যন্ত্র থেকে যন্ত্রে যাওয়া-আসায় সাধারণত এক মিলিসেকেন্ডেরও কম লাগে। মোট ১৩২ ms.
  5. ধাপ ৫ — database. Cache-এ না পেয়ে app database-কে query পাঠায় — ধরা যাক ২৫ ms. ফল পেয়ে app সেটি cache-এ রেখে দেয়, যাতে পরের ক্রেতা উত্তর পান ১ ms-এ। মোট ১৫৭ ms.
  6. ধাপ ৬ — উত্তর ফোনে। উত্তর ফিরতে আরও অর্ধেক RTT, ২০ ms — মোট ১৭৭ ms. খেয়াল করুন: ১০০ ms গেছে শুধু নাম খোঁজা আর হাত মেলানোয়, database-এর ভাগ মাত্র ২৫ ms. Cache-এ পেলে মোট হতো ১৫২ ms; আর একই সংযোগে পরের অনুরোধে (DNS, TCP, TLS বাদ) cache hit হলে মাত্র ৫২ ms.

একই হিসাব এবার ক্যালকুলেটরে — cache-এ পেলে (hit) আর না পেলে (miss) মোট সময় কত, আর প্রতিটি অংশের ভাগ কত শতাংশ:

// Latency budget of ONE request. All times are ASSUMED round numbers (ms).
// Phone <-> data centre round trip time (RTT) = 40 ms; real values vary a lot.
const RTT = 40;
const DNS = 20, HANDSHAKE = 2 * RTT;          // TCP (1 RTT) + TLS 1.3 (1 RTT)
const parts = [
  ["DNS lookup", DNS],
  ["TCP + TLS 1.3 handshakes", HANDSHAKE],
  ["request + response travel", RTT],
  ["load balancer", 1],
  ["app server logic", 10],
  ["cache lookup", 1],
  ["DB query (only on a miss)", 25],
];

function budget(title, path) {
  const total = path.reduce((sum, [, ms]) => sum + ms, 0);
  console.log(`== ${title}: total ${total} ms ==`);
  for (const [name, ms] of path) {
    const pct = (100 * ms / total).toFixed(1);
    console.log(`  ${name.padEnd(27)}${String(ms).padStart(4)} ms ${pct.padStart(5)}%`);
  }
  return total;
}

const hit = budget("cache HIT", parts.slice(0, 6));
const miss = budget("cache MISS", parts);
const inside = (path) => path.slice(3).reduce((sum, [, ms]) => sum + ms, 0);
console.log(`inside the data centre: hit ${inside(parts.slice(0, 6))} ms, miss ${inside(parts)} ms`);
console.log(`reused connection (no DNS/TCP/TLS): hit ${hit - DNS - HANDSHAKE} ms, ` +
            `miss ${miss - DNS - HANDSHAKE} ms`);

আসল রানের আউটপুট:

== cache HIT: total 152 ms ==
  DNS lookup                   20 ms  13.2%
  TCP + TLS 1.3 handshakes     80 ms  52.6%
  request + response travel    40 ms  26.3%
  load balancer                 1 ms   0.7%
  app server logic             10 ms   6.6%
  cache lookup                  1 ms   0.7%
== cache MISS: total 177 ms ==
  DNS lookup                   20 ms  11.3%
  TCP + TLS 1.3 handshakes     80 ms  45.2%
  request + response travel    40 ms  22.6%
  load balancer                 1 ms   0.6%
  app server logic             10 ms   5.6%
  cache lookup                  1 ms   0.6%
  DB query (only on a miss)    25 ms  14.1%
inside the data centre: hit 12 ms, miss 37 ms
reused connection (no DNS/TCP/TLS): hit 52 ms, miss 77 ms

তিনটি শিক্ষা। এক, প্রথম অনুরোধে সবচেয়ে বড় খরচ নেটওয়ার্কে হাত মেলানো: TCP আর TLS একাই hit-এর পথে ৫২.৬%, miss-এর পথে ৪৫.২%. এজন্যই অ্যাপ সংযোগ খোলা রেখে বারবার ব্যবহার করে, আর CDN বা edge সার্ভার কাছে বসিয়ে RTT ছোট করা হয় (পর্ব ৭, ১৭)। দুই, data centre-এর ভেতরে cache-এর প্রভাব বড়: hit-এ ১২ ms, miss-এ ৩৭ ms. তিন, সংযোগ আবার ব্যবহার হলে hit ৫২ ms আর miss ৭৭ ms — তখন database-ই পার্থক্য গড়ে। আর শুধু গড় নয়, সবচেয়ে ধীর ১% অনুরোধের সময়ও (p99) দেখতে হয় — বিস্তারিত পর্ব ০৪-এ।

Cache-এর আসল লাভ — database-এর ভার

Cache-এর বড় জাদু অবশ্য সময়ে নয়, database-এর ভারে। ধরা যাক peak-এ সেকেন্ডে ২০,০০০টি read আসে, আর একটি database সেকেন্ডে ~৫,০০০টি query সামলায়। Cache-এর hit ratio (কত শতাংশ অনুরোধ cache-এই মেটে) যত বাড়ে, database-এ তত কম পৌঁছায়:

// How much read load still reaches the database at each cache hit ratio?
// ASSUMED round numbers: 20,000 reads/s at peak, one DB server ~5,000 queries/s,
// cache lookup ~1 ms, DB query ~25 ms (a miss pays both).
const READS = 20000, DB_CAP = 5000, CACHE_MS = 1, DB_MS = 25;

console.log("hit ratio  DB reads/s  DB servers  avg read time");
for (const h of [0, 0.5, 0.8, 0.9, 0.95, 0.99]) {
  const toDb = READS * (1 - h);                  // only misses reach the DB
  const servers = Math.ceil(toDb / DB_CAP);
  const avgMs = h * CACHE_MS + (1 - h) * (CACHE_MS + DB_MS);
  console.log(`${(h * 100).toFixed(0).padStart(8)}%` + toDb.toFixed(0).padStart(12) +
    String(servers).padStart(12) + avgMs.toFixed(2).padStart(12) + " ms");
}

// The other side of the coin: the cache dies while the DB is sized for 90% hits.
const planned = READS * (1 - 0.9);
console.log(`cache down: DB gets ${READS}/s instead of ${planned.toFixed(0)}/s ` +
            `= ${(READS / planned).toFixed(0)}x the planned load`);

আসল রানের আউটপুট:

hit ratio  DB reads/s  DB servers  avg read time
       0%       20000           4       26.00 ms
      50%       10000           2       13.50 ms
      80%        4000           1        6.00 ms
      90%        2000           1        3.50 ms
      95%        1000           1        2.25 ms
      99%         200           1        1.25 ms
cache down: DB gets 20000/s instead of 2000/s = 10x the planned load

Database-এ পৌঁছায় শুধু miss: ভার = মোট read × (১ − hit ratio). ০% থেকে ৫০%-এ ভার অর্ধেক হলো, কিন্তু ৯০% থেকে ৯৯%-এ আরও ১০ গুণ কমল (২,০০০ → ২০০)। অর্থাৎ শেষের কয়েক শতাংশ hit-ই সবচেয়ে দামি: miss ratio অর্ধেক মানে DB-র ভার অর্ধেক। গড় পড়ার সময়ও ২৬ ms থেকে নামে ১.২৫ ms-এ; আর ০% hit-এ অকেজো cache উল্টো ১ ms বাড়ায়। শেষ লাইনটি সতর্কবার্তা: database যদি ৯০% hit ধরে ছোট রাখা হয়, cache বন্ধ হলেই তাকে ১০ গুণ ভার নিতে হবে — cache তখন ক্ষমতারই অপরিহার্য অংশ। পরের অংশের বিষয় এটাই।

৬ · “এই বাক্সটি মরলে কী হবে?” — single point of failure

System designer-এর সবচেয়ে কাজের অভ্যাস: ছবির প্রতিটি বাক্সে আঙুল রেখে জিজ্ঞেস করা, “এটি এই মুহূর্তে বন্ধ হলে কী হবে?” বড় আকারে বিকল হওয়া নিয়মিত ঘটনা — হাজারো যন্ত্রের মধ্যে প্রায় প্রতিদিনই কোনো disk বা power supply নষ্ট হয়। নিচে প্রতিটি ধাপে একটি করে বাক্স “মেরে” দেখা যাক।

বিকল হওয়ার মহড়া
Architecture
যা বিকল হলো
ফল
প্রতিকার
  1. একটি সার্ভার — পুরোটাই একক বিন্দু। Power supply, disk বা OS — যেকোনো একটিতে সমস্যা মানে পুরো সেবা বন্ধ। যে অংশ একা বিকল হলেই পুরো ব্যবস্থা থেমে যায়, তাকে বলে single point of failure (SPOF). আরও ভয়ের কথা ডেটা: disk নষ্ট হলে আর backup না থাকলে অর্ডারের ইতিহাসও শেষ। তাই প্রথম কাজ backup — redundancy-রও আগে।
  2. App আর DB আলাদা — SPOF বরং দুটি! এখন app মরলেও সেবা বন্ধ, DB মরলেও। প্রতিটির availability ৯৯% হলে দুটি একসাথে চালু থাকার সম্ভাবনা ০.৯৯ × ০.৯৯ = ৯৮.০১% — আগের চেয়ে কম! পরপর (serial) যুক্ত প্রতিটি অংশ availability কমায়; পুরো হিসাব পর্ব ০৫-এ।
  3. তিনটি app সার্ভারের একটি মরল। Load balancer কয়েক সেকেন্ড পরপর প্রতিটি সার্ভারকে একটি ছোট অনুরোধ পাঠিয়ে দেখে সাড়া আসে কি না — একে বলে health check. সাড়া না পেলে সার্ভারটি বাদ; ব্যবহারকারী টেরও পান না, শুধু ক্ষমতা কমল এক-তৃতীয়াংশ। তাই হিসাব হয় N+1: একটি কম থাকলেও যেন peak সামলানো যায়। একের বেশি কপি রাখার এই কৌশলের নাম redundancy.
  4. একমাত্র load balancer মরল। তিনটি app সার্ভার দিব্যি সুস্থ, তবু কেউ পৌঁছাতে পারছেন না — দরজা একটাই। সমাধান LB-রও জোড়া: একটি সক্রিয়, অন্যটি প্রস্তুত (active-passive), দুটির হাতে একই virtual IP; অথবা DNS-এ একাধিক LB-র ঠিকানা। বিস্তারিত পর্ব ১৪-এ।
  5. Cache মরল — লুকানো SPOF. Cache-এর ডেটা হারালে ক্ষতি নেই, মূল কপি DB-তে। কিন্তু ক্ষমতা? DB যদি ৯০% hit ধরে মাপা হয়ে থাকে, cache বন্ধ হলেই তার ভার ১০ গুণ (অংশ ৫-এর cache-হিসাবের শেষ লাইন) — DB-ও ভেঙে পড়ে। এক অংশের ব্যর্থতা এভাবে আরেক অংশে ছড়ানোকে বলে cascading failure.
  6. DB primary মরল। পড়া চলছে replica থেকে, কিন্তু লেখা বন্ধ — নতুন অর্ডার নেওয়া যাচ্ছে না। একটি replica-কে নতুন primary বানাতে হয়; বিকল অংশের দায়িত্ব এভাবে অন্যকে দেওয়ার নাম failover. Replication async হলে primary-র শেষ কয়েকটি লেখা হারাতে পারে; কতটা হারানো চলে, সেই সিদ্ধান্ত ব্যবসার, প্রকৌশলীর একার নয় (পর্ব ২২, ৫১)।
  7. পুরো region বসে গেল। একটি data centre-এ বিদ্যুৎ বিভ্রাট, বন্যা বা fiber কাটা — ভেতরের সব redundancy একসাথে অচল। দ্বিতীয় region থাকলে DNS ব্যবহারকারীদের সেখানে পাঠায়। কত মিনিটে সেবা ফিরবে (RTO) আর কত মিনিটের ডেটা হারানো চলবে (RPO), দুটোই আগে ঠিক করে নিয়মিত মহড়া দিতে হয়।
  8. সবচেয়ে চতুর SPOF — একটি ভুল config. সব সার্ভার, সব region একই config আর একই নতুন কোড পায়। একটি ভুল কমান্ড বা config একসাথে সবখানে ছড়ালে redundancy কাজে আসে না — বাস্তবের বহু বড় বিভ্রাট এভাবেই ঘটেছে (ভাবনার প্রশ্ন ৪)। প্রতিকার প্রক্রিয়ায়: আগে অল্প কিছু যন্ত্রে release, স্বয়ংক্রিয় যাচাই, আর দ্রুত আগের অবস্থায় ফেরা (পর্ব ৫৩)।
নিয়ম

প্রতিটি স্তরে অন্তত দুটি (redundancy), কে সুস্থ তা জানার উপায় (health check), আর একটি বিকল হলে আরেকটিতে সরে যাওয়ার ব্যবস্থা (failover). হিসাবটা চমকপ্রদ: দুটি ৯৯%-এর অংশ পরপর থাকলে মোট ৯৮.০১%, কিন্তু পাশাপাশি থাকলে (যেকোনো একটি চললেই হয়, আর দুটির বিকল হওয়া পরস্পর-নির্ভর না হলে) ১ − ০.০১ × ০.০১ = ৯৯.৯৯%. তবে redundancy সব রক্ষা করে না: সব কপিতে একই ভুল config বা একই বাগ একসাথে পৌঁছালে সবাই একসাথে পড়ে।

৭ · System design-এর ইট — building block-গুলো এক নজরে

সেবা যত বড়ই হোক, ঘুরেফিরে কয়েকটি একই ধরনের ইট দিয়ে গড়া। প্রতিটির ভেতরের কৌশল পরের মডিউলগুলোর বিষয়; এখন শুধু চিনে রাখুন কে কী করে:

ইটএক লাইনে কাজকোথায় বিস্তারিত
DNSনাম থেকে IP ঠিকানা; অনেক সময় কাছের বা সুস্থ region বেছে দেয়পর্ব ৭
CDNছবি, CSS, JavaScript, ভিডিওর কপি ব্যবহারকারীর কাছের সার্ভারেপর্ব ১৭ (মডিউল ৩)
Load balancerঅনুরোধ সুস্থ সার্ভারগুলোর মধ্যে ভাগ করে দেয়পর্ব ১৪; API gateway পর্ব ১১
App / service স্তরব্যবসার নিয়ম চালায়; stateless হলে সহজে বাড়ানো যায়পর্ব ১৩, ১৫, ৪৭
Cacheবারবার চাওয়া ডেটার কপি মেমরিতেমডিউল ৫ (পর্ব ২৮–৩০)
SQL databaseটেবিল, transaction, join — কঠোর নিয়মের ডেটামডিউল ৪ (পর্ব ১৯–২৫)
NoSQL databasekey-value, document, wide-column, graph; ভাগ করে বাড়ানো সহজপর্ব ২০
Object storageছবি, ভিডিও, backup — বড় ফাইল সস্তায়, অনেক কপিতেপর্ব ২৬
Queue / streamধীর কাজ পরে করা; ঘটনার ধারাবাহিক লগ রাখামডিউল ৬ (পর্ব ৩১–৩৭)
Searchশব্দ দিয়ে খোঁজা — inverted index দিয়েপর্ব ২৭
Monitoringlog, metric, trace আর alert — ভেতরে কী ঘটছে দেখাপর্ব ৫০

বড় হয়ে ওঠা একটি সেবার পূর্ণ architecture

DNS, CDN, load balancer, stateless apps, cache, queue, search, sharded database, object storage, monitoring, two regions

বড় হয়ে ওঠা একটি সেবার পূর্ণ architecture ব্যবহারকারী, DNS, CDN আর object storage; load balancer হয়ে তিনটি stateless app; cache, queue, worker আর search; দুটি database shard, প্রতিটিতে primary আর replica; monitoring; আর region ২-এ পুরো ডেটার কপি। Region ১ (একটি data centre) DNS কোন region? ব্যবহারকারী ফোন · ব্রাউজার CDN ছবি · JS · CSS Load balancer Object storage App ১ stateless App ২ stateless App ৩ stateless Cache গরম ডেটা Queue ধীর কাজ Search পণ্য খোঁজা DB shard A primary replica DB shard B primary replica Worker SMS · ইমেইল Monitoring: log · metric · trace · alert Region ২ — পুরো সেটআপের কপি ডেটা replication
ছবি ১.১ — ধাপ ৯-এর পরের পূর্ণ ছবি। তীর অনুরোধের দিক দেখায়; ড্যাশ দাগ কপি বা বিকল্প পথ। বাস্তবে প্রতিটি বাক্সই একাধিক যন্ত্র।

ছবিতে একটি অনুরোধের পথ মিলিয়ে দেখুন। ফোন DNS থেকে সুস্থ আর কাছের region-এর ঠিকানা পায়। ছবি আর CSS আসে CDN থেকে; CDN-এর কাছে না থাকলে সে object storage থেকে এনে রাখে। আসল অনুরোধ load balancer হয়ে যায় একটি app সার্ভারে; app আগে cache দেখে, না পেলে গ্রাহকের id দেখে ঠিক shard-এ যায়। খোঁজা যায় search-এ, ধীর কাজ queue-তে। আর monitoring সব স্তর থেকে তথ্য জোগাড় করে — কিছু ভাঙলে প্রথম খবর আসে সেখান থেকেই।

৮ · ভালো নকশার মাপকাঠি আর trade-off-এর মন

একটি নকশা ভালো না খারাপ, তা মাপা হয় কয়েকটি গুণ দিয়ে: scalability (ভার বাড়লে যন্ত্র যোগ করে সামলানো যায় কি না), availability (কত শতাংশ সময় চালু), latency (কত দ্রুত উত্তর, বিশেষ করে ধীরতম অনুরোধে), consistency (সবাই একই, হালনাগাদ ডেটা দেখেন কি না), durability (একবার “সেভ হয়েছে” বললে ডেটা আর হারায় না), খরচ, আর maintainability (বুঝতে, চালাতে আর বদলাতে সহজ কি না)। এগুলোকে বলে non-functional requirement; কোনটি কতটা দরকার, তা ঠিক হয় ব্যবসা থেকে — পর্ব ০২-এর বিষয়।

“Consistency” শব্দের মানে প্রসঙ্গভেদে আলাদা। Database transaction-এর ACID-এ এর মানে, ডেটা কখনো নিয়ম (যেমন “ব্যালান্স ঋণাত্মক হবে না”) ভাঙবে না। Distributed system-এর CAP-এ এর মানে, সব কপি একই সর্বশেষ মান দেখায়। একই শব্দ, দুটি আলাদা ধারণা — পর্ব ২৪ আর ৪০-এ দুটিকে আলাদা করে দেখবেন।

নিখুঁত নকশা বলে কিছু নেই। প্রতিটি সিদ্ধান্ত একটি সুবিধা কেনে, আর তার দাম দেয় অন্য কোথাও — একেই বলে trade-off. ভালো প্রকৌশলী “সেরা কোনটা?” জিজ্ঞেস করেন না; জিজ্ঞেস করেন, “এই পরিস্থিতিতে কোন দামটা দিতে রাজি?” তিনটি উদাহরণ:

Cache: গতি বনাম টাটকা ডেটা

Cache উত্তর দেয় প্রায় ১ ms-এ আর DB-র ভার কমায়, কিন্তু DB-তে দাম বদলালে cache-এ কিছুক্ষণ পুরোনো দাম থেকে যেতে পারে। পণ্যের ছবির জন্য ১০ মিনিট পুরোনো চলে; ব্যাংকের ব্যালান্সের জন্য চলে না।

পর্ব ২৮–২৯

Replication: নিরাপত্তা বনাম লেখার গতি

প্রতিটি লেখা দূরের কপিতে পৌঁছানো পর্যন্ত অপেক্ষা করলে (synchronous) ডেটা হারায় না, কিন্তু প্রতিটি লেখা ধীর হয়। অপেক্ষা না করলে (asynchronous) লেখা দ্রুত, কিন্তু primary হঠাৎ বিকল হলে শেষ কয়েকটি লেখা হারাতে পারে।

পর্ব ২২, ৪০

Queue: দ্রুত উত্তর বনাম তাৎক্ষণিক নিশ্চয়তা

Queue-তে কাজ রেখে সঙ্গে সঙ্গে “পেয়েছি” বললে ব্যবহারকারী অপেক্ষা করেন না, কিন্তু কাজটি হয় পরে — SMS হয়তো এক মিনিট পরে আসে, আর বিকল হয়ে আবার চেষ্টায় একই কাজ দুবারও হতে পারে। তাই কাজগুলোকে idempotent বানাতে হয়: দুবার করলেও ফল একবারের মতো।

পর্ব ৩১, ৩৪

তিনটির কোনোটিতেই সর্বজনীন “সঠিক উত্তর” নেই, আছে প্রেক্ষাপট: একই প্রশ্নের উত্তর খবরের সাইটে এক রকম, mobile banking সেবায় আরেক রকম। তাই প্রতিটি সিদ্ধান্তের পাশে তার কারণ আর দাম লিখে রাখা হয়।

আরও গভীরে: Martin Abbott আর Michael Fisher তাঁদের বই The Art of Scalability-তে (২০০৯) scaling-কে তিন অক্ষে ভাগ করেছেন, যা “AKF scale cube” নামে পরিচিত: X-অক্ষে একই জিনিসের কপি (আমাদের ধাপ ৩ আর ৫), Y-অক্ষে কাজ ভাগ করে আলাদা সেবা (queue-worker, microservices), আর Z-অক্ষে ডেটা ভাগ (sharding, ধাপ ৮)। বড় পরিসরের নকশা নিয়ে গভীরে যেতে প্রায়ই সুপারিশ করা হয় Martin Kleppmann-এর Designing Data-Intensive Applications (২০১৭) আর Google-এর Luiz André Barroso ও Urs Hölzle-এর The Datacenter as a Computer (প্রথম সংস্করণ ২০০৯)।

৯ · System design কোথায় লাগে, আর এই কোর্স কীভাবে সাজানো

System design-এর দেখা পাবেন তিন জায়গায়:

  • বিশ্ববিদ্যালয়ে: Software Architecture, Distributed Systems, Cloud Computing আর Web Engineering-এর মতো কোর্সে — সংজ্ঞা, তুলনা (vertical বনাম horizontal, SQL বনাম NoSQL), ছোট নকশা বা হিসাব হিসেবে।
  • চাকরির ইন্টারভিউতে: backend, full-stack, SRE/DevOps আর অভিজ্ঞ পদে প্রায়ই প্রায় এক ঘণ্টার একটি খোলা প্রশ্ন — “একটি URL shortener নকশা করুন।” শুদ্ধ উত্তরের চেয়ে বেশি দেখা হয় চিন্তার ধারা: প্রশ্ন করে প্রয়োজন বের করা, হিসাব, trade-off-এর ব্যাখ্যা। কাঠামো পর্ব ০৬-এ, পূর্ণ অনুশীলন মডিউল ১০-এ।
  • কাজের জায়গায়: বড় ফিচার বানানোর আগে দলগুলো একটি design doc লেখে — সমস্যা, বিকল্প, বেছে নেওয়া পথ, তার দাম আর ঝুঁকি; তারপর design review-তে সহকর্মীরা প্রশ্ন করেন। ভুল কাগজে ধরা পড়লে সবচেয়ে সস্তা।

কোর্সের মানচিত্র — ১০টি মডিউল, ৬৬টি পর্ব

মডিউলবিষয়পর্বযা পাবেন
১System Design-এর ভিত্তি০১–০৬প্রয়োজন আর trade-off, মোটা দাগের হিসাব, latency-percentile, availability, নকশার ধাপ
২যোগাযোগ আর API০৭–১২নকশার জন্য networking, REST, gRPC-GraphQL, WebSocket, API gateway, serialization
৩Scaling-এর মৌলিক১৩–১৮vertical বনাম horizontal, load balancing, session, consistent hashing, CDN, overload সামলানো
৪ডেটা স্টোরেজ১৯–২৭storage engine, SQL বনাম NoSQL, index, replication, sharding, transaction, object storage, search
৫Caching২৮–৩০cache-এর কৌশল, eviction আর invalidation, distributed cache
৬Messaging আর stream৩১–৩৭queue, pub/sub, log-ভিত্তিক stream, delivery semantics, event sourcing, batch-stream, workflow
৭Distributed systems-এর তত্ত্ব৩৮–৪৬partial failure, clock, CAP, quorum, Raft, lock, gossip, Bloom filter, CRDT
৮Architecture, reliability আর operations৪৭–৫৩microservices, resilience pattern, rate limiting, observability, disaster recovery, নিরাপত্তা, deployment
৯Case study৫৪–৬১URL shortener, chat, news feed, notification, ride-sharing, video, ticket booking, ক্যাপস্টোন key-value store
১০পরীক্ষা ও ইন্টারভিউ প্রস্তুতি৬২–৬৬হিসাবের অনুশীলন, MCQ, লিখিত ও ভাইভা, ধারণাভিত্তিক প্রশ্ন, পূর্ণ mock interview

পূর্বপ্রস্তুতি — কী জানা থাকলে সুবিধা

পরীক্ষা ও ইন্টারভিউতে এই বিষয়ে প্রায়ই যা জিজ্ঞেস করা হয়:

  • System design কী? HLD আর LLD-র পার্থক্য? — HLD পুরো সেবার উপাদান, সংযোগ, ডেটার পথ আর ব্যর্থতায় আচরণ ঠিক করে; LLD একটি সার্ভিসের ভেতরের class, interface আর pattern.
  • Vertical আর horizontal scaling-এর পার্থক্য? — বড় মেশিন বনাম বেশি মেশিন; প্রথমটি সহজ কিন্তু ছাদ আছে আর SPOF থাকে, দ্বিতীয়টিতে লাগে load balancer আর stateless সার্ভার।
  • ১ কোটি DAU, প্রতি জন দিনে ২০টি অনুরোধ — গড় আর peak QPS? — গড় = ১,০০,০০,০০০ × ২০ ÷ ৮৬,৪০০ ≈ ২,৩১৫; peak factor ৩ ধরলে ≈ ৬,৯৪৪.
  • Single point of failure কী, কীভাবে দূর করবেন? — যে অংশ একা বিকল হলে পুরো সেবা বন্ধ; প্রতিকার redundancy, health check আর failover.
  • Cache কেন, আর তার দাম কী? — দ্রুত read আর DB-র ভার কমানো; দাম পুরোনো ডেটার সম্ভাবনা, invalidation-এর জটিলতা, আর cache বিকল হলে DB-তে হঠাৎ ভার।

১০ · AI-এর যুগে system design — সহকারী, বিচারক নয়

AI-এর কাছে একটি খাবার-ডেলিভারি অ্যাপের system design চাইলে কয়েক সেকেন্ডে সুন্দর উত্তর আসে — microservices, Kafka, Redis, Kubernetes, সবই আছে। উত্তরটি দেখতে নিখুঁত, কিন্তু প্রায়ই আপনার প্রয়োজনের সাথে মেলে না। AI-এর ভুলগুলো নির্দিষ্ট ধরনের, আর আসে আত্মবিশ্বাসী সুরে:

AI-এর ভুলউদাহরণকীভাবে যাচাই করবেন
সব জায়গায় এক উত্তর“Kafka, Redis আর microservices যোগ করুন” — ১০ হাজার DAU-র অ্যাপের জন্যওআগে QPS হিসাব (অংশ ৪); প্রতিটি বাক্সের পাশে লিখুন সে কোন সমস্যা সমাধান করছে
হিসাবের ভুলদিনের সেকেন্ডের জায়গায় ঘণ্টার সেকেন্ড দিয়ে ভাগ, bit আর byte গুলিয়ে ফেলাপ্রতিটি ধাপ নিজে আবার করুন, একক মিলিয়ে
ব্যর্থতা উপেক্ষাএকমাত্র load balancer; cache বিকল হলে DB-র কী হবে, তার উল্লেখ নেইপ্রতিটি বাক্সে “এটি মরলে?” (অংশ ৬)
ACID আর CAP-এর consistency গুলিয়ে ফেলা“database-টি ACID মানে, তাই CAP-এর consistency-ও আছে”দুটি সংজ্ঞা আলাদা করে লিখুন (পর্ব ২৪, ৪০)
বানানো সীমা আর দামকোনো cloud সেবার নির্দিষ্ট সীমা বা দাম আত্মবিশ্বাসের সাথে বলাঅফিসিয়াল ডকুমেন্টেশন আর দামের পাতা, তারিখসহ
প্রয়োজনের চেয়ে বড় নকশাপ্রথম দিনেই বহু region আর এক ডজন microservice“সবচেয়ে সরল কোন নকশা কাজ করবে?” জিজ্ঞেস করুন; ছোট load test বা simulation চালান

AI-কে নকশার সঙ্গী বানাতে প্রশ্নে সংখ্যা, শর্ত আর যাচাইয়ের দাবি জুড়ে দিন। নিচের তথ্যে আমাদের ক্যালকুলেটর দেয় peak ২৭৭.৮ অনুরোধ/সেকেন্ড — ধাপ ২-ই যথেষ্ট; উত্তরে Kafka আর microservices এলে জিজ্ঞেস করুন, কেন।

তুমি একজন অভিজ্ঞ backend architect-এর মতো উত্তর দাও। আমি একটি অনলাইন বাজারের অ্যাপের নকশা করছি। তথ্য: DAU ২ লাখ, প্রতি জন দিনে গড়ে ৪০টি অনুরোধ, peak factor ৩, আর ৯৫% অনুরোধ শুধু তথ্য পড়ে। ১. প্রথমে গড় আর peak QPS হিসাব করো, প্রতিটি ধাপ লিখে। ২. এই ভারের জন্য সবচেয়ে সরল কোন architecture যথেষ্ট, বলো। প্রতিটি উপাদানের পাশে লেখো সে কোন সমস্যা সমাধান করছে; দরকার না হলে কিছু যোগ কোরো না। ৩. প্রতিটি উপাদান বিকল হলে কী ঘটবে আর প্রতিকার কী, একটি তালিকা দাও। ৪. কোথায় কোথায় consistency-র trade-off আছে, বলো; ACID আর CAP-এর consistency আলাদা করে লেখো। ৫. কোনো সেবার নির্দিষ্ট সীমা বা দাম বললে উৎস দাও; নিশ্চিত না হলে "নিশ্চিত নই" লেখো।

AI-এর নকশা হাতে পেলে — যাচাইয়ের চেকলিস্ট

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন — তারপর “→ উত্তর” চাপুন।

প্র ০১Microservices কি আধুনিক নকশার প্রথম ধাপ হওয়া উচিত? Monolith দিয়ে শুরু করা কি পিছিয়ে থাকা?

না — বরং বহু অভিজ্ঞ প্রকৌশলীর পরামর্শ উল্টো। Monolith মানে পুরো অ্যাপ একটি প্রোগ্রাম হিসেবে তৈরি আর deploy হয়; microservices মানে অ্যাপকে অনেক ছোট, আলাদাভাবে deploy করা সেবায় ভাগ করা, যারা network দিয়ে কথা বলে। দ্বিতীয়টির সুবিধা স্পষ্ট: আলাদা দল নিজের গতিতে কাজ করতে পারে, আর আলাদা অংশ আলাদাভাবে বাড়ানো যায়। কিন্তু দামও বড়: প্রতিটি function call এখন network call — ধীর, আর যেকোনো সময় ব্যর্থ হতে পারে; ডেটা ভাগ হয়ে যায়; একটি অনুরোধের সমস্যা খুঁজতে দশটি সেবার log ঘাঁটতে হয়।

১৯৬৮ সালে Melvin Conway-এর একটি প্রবন্ধে একটি পর্যবেক্ষণ প্রকাশিত হয়, যা পরে “Conway's law” নামে পরিচিত: একটি প্রতিষ্ঠান যে সিস্টেম বানায়, তার গঠন হয় প্রতিষ্ঠানের যোগাযোগের কাঠামোর মতো। অর্থাৎ microservices মূলত বড় প্রতিষ্ঠানের সমাধান — যখন শত শত প্রকৌশলী একই কোডে কাজ করতে গিয়ে একে অপরের পথ আটকান। ২০১৫ সালে Martin Fowler তাঁর “MonolithFirst” লেখায় যুক্তি দেন: শুরুতে সেবাগুলোর সীমারেখা কোথায় টানা উচিত, তা সাধারণত জানা থাকে না, আর ভুল জায়গায় ভাগ করলে পরে জোড়া লাগানো কঠিন।

উল্টো দিকের বাস্তব উদাহরণও আছে। ২০২৩ সালে Amazon Prime Video-র দলের প্রকাশিত একটি engineering blog অনুযায়ী, ভিডিওর মান পর্যবেক্ষণের একটি নির্দিষ্ট সেবাকে আলাদা আলাদা বিতরণকৃত উপাদানের নকশা থেকে একটি একক প্রক্রিয়ায় ফিরিয়ে আনায় সেই সেবার অবকাঠামোর খরচ ৯০%-এর বেশি কমে। এটি microservices-বিরোধী রায় নয় — একটি নির্দিষ্ট কাজের জন্য একটি নির্দিষ্ট সিদ্ধান্ত, মাপজোখের ভিত্তিতে।

মূল উপলব্ধি: Architecture বাছাই হয় দল, ভার আর পরিবর্তনের গতি দেখে, চলতি ফ্যাশন দেখে নয়। ভেতরে পরিষ্কার module-এ সাজানো একটি monolith দিয়ে শুরু করে, যেখানে সত্যিই দরকার সেখান থেকে আলাদা সেবা বের করা — এটাই সাধারণত নিরাপদ পথ (পর্ব ৪৭)।

প্র ০২দ্বিগুণ সার্ভার মানে কি দ্বিগুণ ক্ষমতা? তাহলে শুধু সার্ভার যোগ করে গেলেই হয় না কেন?

যতক্ষণ কাজগুলো একে অপরের ওপর নির্ভর করে না, ততক্ষণ প্রায় হ্যাঁ — stateless app সার্ভার এজন্যই সহজে বাড়ে। কিন্তু প্রতিটি সিস্টেমে কিছু অংশ থাকে যা ভাগ করা যায় না: একটি primary database, একটি lock, একটি কেন্দ্রীয় counter. ১৯৬৭ সালে IBM-এর প্রকৌশলী Gene Amdahl এই সীমা একটি সরল সূত্রে দেখান: কাজের p অংশ সমান্তরালে চলতে পারলে N গুণ যন্ত্রে গতি বাড়ে সর্বোচ্চ ১ ÷ ((১ − p) + p ÷ N) গুণ।

ধরা যাক ৯৫% কাজ ভাগ করা যায়, আর ৫% যায় একটি কেন্দ্রীয় অংশ দিয়ে। তাহলে ১০টি সার্ভারে লাভ ১০ গুণ নয়, প্রায় ৬.৯ গুণ; ১০০টিতে প্রায় ১৬.৮ গুণ; আর অসীম সার্ভারেও ২০ গুণের বেশি নয় — ওই ৫%-ই দেয়াল।

বাস্তব আরও কঠিন। ১৯৯০-এর দশকে Neil Gunther তাঁর Universal Scalability Law-এ আরেকটি খরচ যোগ করেন: যন্ত্রগুলোকে নিজেদের মধ্যে তথ্য মিলিয়ে নিতে হয় (coherence), আর সেই খরচ বাড়ে প্রায় যন্ত্রসংখ্যার বর্গের হারে। সূত্রটি C(N) = N ÷ (১ + α(N − ১) + βN(N − ১)); β শূন্য না হলে একটি নির্দিষ্ট N-এর পর যন্ত্র যোগ করলে ক্ষমতা উল্টো কমে। যেমন α = ০.০৫ আর β = ০.০০১ হলে সর্বোচ্চ ক্ষমতা আসে প্রায় ৩১টি যন্ত্রে, তাও মাত্র ৯ গুণের কাছাকাছি; ১০০টি যন্ত্রে তা নেমে আসে প্রায় ৬.৩ গুণে।

এজন্যই system design-এর বড় অংশ হলো ভাগ-না-হওয়া অংশ খুঁজে বের করে ছোট করা: session-কে সার্ভার থেকে সরানো (stateless), database-কে replica আর shard-এ ভাগ করা, কেন্দ্রীয় lock এড়ানো, আর যেখানে সম্ভব যন্ত্রগুলোকে একে অপরের অপেক্ষায় না রাখা।

মূল উপলব্ধি: Scalability মানে শুধু “আরও যন্ত্র” নয়; মানে এমন নকশা, যেখানে যন্ত্রগুলোকে কম অপেক্ষা আর কম সমন্বয় করতে হয়। কোন অংশ ভাগ হয় না, সেটি আগে খুঁজুন।

প্র ০৩একটি সার্ভার থেকে অনেক সার্ভারে গেলে প্রোগ্রামারের কোন চেনা ধারণাগুলো ভেঙে যায়?

এক যন্ত্রে একটি function call হয় সফল, নয় ব্যর্থ। অনেক যন্ত্রে network-এর ওপারে অনুরোধ পাঠালে তৃতীয় একটি অবস্থা আসে: উত্তর এলো না, আর কাজটি হয়েছে কি না, তাও জানা নেই। ১৯৯০-এর দশকে Sun Microsystems-এর প্রকৌশলীরা এমন কিছু ভুল ধারণার তালিকা করেন, যা “fallacies of distributed computing” নামে বিখ্যাত; প্রচলিত মতে প্রথম সাতটি L Peter Deutsch-এর (১৯৯৪), আর অষ্টমটি James Gosling-এর যোগ করা (১৯৯৭)। ভুল ধারণাগুলো: network নির্ভরযোগ্য; latency শূন্য; bandwidth অসীম; network নিরাপদ; topology বদলায় না; administrator একজনই; ডেটা পাঠানোর খরচ শূন্য; আর network সমজাতীয়।

আমাদের গল্পের প্রতিটি ধাপে এগুলোর কোনো না কোনোটি সামনে আসে। ধাপ ২-এ database অন্য যন্ত্রে গেল — প্রতিটি query-তে এখন network-এর দেরি যোগ হয়। ধাপ ৩-এ app সার্ভার যোগ-বাদ হয়, অর্থাৎ topology বদলায়। ধাপ ৫-এ replica-তে লেখা পৌঁছায় দেরিতে, তাই “সবাই একই ডেটা দেখে” আর সত্য নয়। ধাপ ৭-এ queue-র বার্তা হারাতে পারে বা দুবার আসতে পারে। ধাপ ৯-এ দুই region-এর মাঝের fiber কাটা গেলে দুই পক্ষই ভাবতে পারে অন্যজন মৃত, আর দুজনেই নিজেকে প্রধান ভেবে লেখা নিতে শুরু করতে পারে।

এসবের জবাবেই system design-এর বহু কৌশলের জন্ম: timeout আর retry (পর্ব ৪৮), idempotency (পর্ব ৩৪), consensus (পর্ব ৪২), আর ঘড়ির ওপর ভরসা না করে ঘটনার ক্রম বোঝা (পর্ব ৩৯)। পুরো মডিউল ৭ এই কঠিন সত্যগুলো নিয়ে।

মূল উপলব্ধি: Distributed system মানে শুধু “বেশি যন্ত্র” নয় — মানে আংশিক ব্যর্থতা (partial failure) স্বাভাবিক ঘটনা হয়ে ওঠা। ভালো নকশা ধরে নেয়, network ধীর, অনির্ভরযোগ্য আর পরিবর্তনশীল — এবং তবুও সঠিক থাকে।

প্র ০৪বড় বড় বিভ্রাট (outage) থেকে single point of failure সম্পর্কে কী শেখা যায়?

অনেকের ধারণা, SPOF মানে একটি একক সার্ভার। বাস্তবের বড় বিভ্রাটগুলো দেখায়, SPOF প্রায়ই অদৃশ্য — একটি কমান্ড, একটি config, একটি শেয়ার করা নির্ভরতা।

২০১৭ সালের ২৮ ফেব্রুয়ারি Amazon-এর S3 storage সেবা তাদের US-EAST-1 region-এ কয়েক ঘণ্টা বিঘ্নিত হয়, আর এর ওপর নির্ভরশীল অসংখ্য ওয়েবসাইট আর অ্যাপও সমস্যায় পড়ে। AWS-এর প্রকাশিত সারাংশ অনুযায়ী, একজন প্রকৌশলী নির্ধারিত নিয়ম মেনে অল্প কিছু সার্ভার সরাতে একটি কমান্ড চালান, কিন্তু একটি ইনপুট ভুল লেখা হওয়ায় অনেক বেশি সার্ভার সরে যায়। পরিহাসের বিষয়, সেবার অবস্থা জানানোর ড্যাশবোর্ডও কিছুক্ষণ হালনাগাদ করা যায়নি, কারণ সেটিও S3-এর ওপর নির্ভর করত।

২০২১ সালের ৪ অক্টোবর Facebook, Instagram আর WhatsApp প্রায় ছয় ঘণ্টা বন্ধ ছিল। প্রতিষ্ঠানটির engineering blog অনুযায়ী, রক্ষণাবেক্ষণের সময় দেওয়া একটি কমান্ড তাদের backbone network-এর সব সংযোগ বিচ্ছিন্ন করে দেয়; এমন কমান্ড আটকানোর যাচাই-টুলে বাগ থাকায় সেটি থামানো যায়নি। এরপর তাদের DNS সার্ভারগুলো নিজেদের ঠিকানা ইন্টারনেটে ঘোষণা করা বন্ধ করে দেয়, ফলে বাইরের পৃথিবী তাদের খুঁজেই পাচ্ছিল না। ভেতরের টুলগুলোও একই network-এর ওপর নির্ভরশীল হওয়ায় সমাধানে প্রকৌশলীদের সশরীরে data centre-এ যেতে হয়।

শিক্ষা কয়েকটি। এক, redundancy-র কপিগুলো যদি একই config, একই কমান্ড বা একই কোড একসাথে পায়, তারা একসাথে পড়ে। দুই, মেরামতের টুল যেন সেই সিস্টেমের ওপর নির্ভর না করে, যেটি মেরামত করতে হবে। তিন, ক্ষতির পরিসর (blast radius) ছোট রাখতে পরিবর্তন ধাপে ধাপে ছড়াতে হয় — আগে অল্প কিছু যন্ত্রে, তারপর বাকিগুলোতে।

মূল উপলব্ধি: “এই বাক্সটি মরলে কী হবে?” প্রশ্নটি শুধু সার্ভারের জন্য নয় — config, deploy-প্রক্রিয়া, DNS, এমনকি মানুষের একটি টাইপের ভুলের জন্যও করতে হয়।

প্র ০৫শুরু থেকেই কোটি ব্যবহারকারীর জন্য নকশা করা কি বুদ্ধিমানের কাজ? কতটুকু আগাম প্রস্তুতি ঠিক?

দুই দিকেই খাদ। খুব কম প্রস্তুতিতে ভিড়ের দিনে সেবা ভেঙে পড়ে — ফল প্রকাশের দিনের সাইট বা ঈদের সেলের প্রথম মিনিট। খুব বেশি প্রস্তুতিতে যে সমস্যা হয়তো কখনো আসবে না, তার পেছনে মাসের পর মাস আর টাকা যায়; আর অতিরিক্ত জটিলতা নিজেই নতুন বাগ আর বিভ্রাটের উৎস হয়ে ওঠে।

১৯৭৪ সালে Donald Knuth তাঁর একটি প্রবন্ধে লেখেন, অকালে optimization করা “সব অনিষ্টের মূল” — সাথে এটাও বলেন যে গুরুত্বপূর্ণ ৩%-এর সুযোগ হাতছাড়া করা উচিত নয়। Extreme Programming আন্দোলন একই চিন্তাকে বলে YAGNI — “You Aren't Gonna Need It”. বাস্তব উদাহরণ: Stack Overflow-এর প্রকৌশলীদের প্রকাশিত লেখা (২০১৬) অনুযায়ী, বিশ্বের অন্যতম ব্যস্ত প্রশ্নোত্তর সাইটটি তখন হাতে গোনা কয়েকটি ওয়েব সার্ভার আর কয়েকটি শক্তিশালী SQL Server দিয়ে চলত — monolith, ভালো index, cache আর নিয়মিত মাপজোখের জোরে।

তাহলে কতটুকু? একটি কাজের নিয়ম: এখনকার peak-এর কয়েক গুণ (ধরা যাক ৩ থেকে ১০ গুণ) সামলানোর মতো নকশা করুন, আর এমনভাবে করুন যাতে পরের ধাপে যাওয়া সহজ থাকে — যেমন app সার্ভার শুরু থেকেই stateless রাখা, database-এর ঠিকানা config-এ রাখা, আর ডেটায় এমন id রাখা যা পরে shard করতে সুবিধা দেয়। এগুলো সস্তা, কিন্তু ভবিষ্যতের দরজা খোলা রাখে। আর যেসব ক্ষতি ফেরানো যায় না — ডেটা হারানো, নিরাপত্তার ফাঁক — সেখানে শুরু থেকেই কোনো ছাড় নেই: backup আর encryption প্রথম দিন থেকে।

মূল উপলব্ধি: ভালো নকশা আজকের সমস্যা সরলভাবে সমাধান করে আর আগামীকালের বদলকে সস্তা রাখে। যে সিদ্ধান্ত ফেরানো যায়, তাতে দ্রুত চলুন; যা ফেরানো যায় না, তাতে ধীরে।

অনুশীলন

হাতে হিসাব, নকশার সমালোচনা আর আউটপুট অনুমান — আগে নিজে চেষ্টা করুন, তারপর উত্তর মেলান।

  1. Bottleneck খুঁজুন: একটি অ্যাপে আছে একটি load balancer, ৪টি app সার্ভার (প্রতিটির CPU ৩০%), আর একটি database (CPU ৯৫%, disk সারাক্ষণ ব্যস্ত)। ৯০% query শুধু পড়া, তার বেশির ভাগ একই ২০০টি জনপ্রিয় পণ্যের পাতা। গত সপ্তাহ থেকে p99 latency ১২০ ms থেকে বেড়ে ১.৫ সেকেন্ড। দলের একজন বলছেন, “আরও ৪টি app সার্ভার যোগ করি।” আপনি কী বলবেন, আর প্রথম তিনটি পদক্ষেপ কী?

    Bottleneck database: app সার্ভারগুলো ৩০%-এ বসে, DB ৯৫%-এ। আরও app সার্ভার মানে একসাথে আরও query আর connection — DB-র অবস্থা আরও খারাপ। পদক্ষেপ:

    • মাপুন: সবচেয়ে ধীর আর সবচেয়ে ঘন ঘন query কোনগুলো; প্রায়ই একটি অনুপস্থিত index-ই আসল কারণ (পর্ব ২১)।
    • জনপ্রিয় ২০০টি পাতা cache-এ: read-এর ৯০% cache থেকে মিটলে DB-তে যায় মোট query-র ০.৯ × ০.১ + ০.১ = ১৯%. CPU query-সংখ্যার সমানুপাতিক ধরলে ৯৫% থেকে মোটামুটি ১৮%-এ নামতে পারে — বাস্তবে মেপে দেখবেন (পর্ব ২৮)।
    • তারপরও দরকার হলে: read replica (পর্ব ২২) আর connection pool.

    শিক্ষা: যে অংশ ভরে আছে, সেখানে হাত দিন; খালি অংশ বড় করে লাভ নেই।

  2. একটি সার্ভার কখন যথেষ্ট নয় (হিসাব): Load test-এ মাপা গেছে, আপনার একটি সার্ভার সেকেন্ডে ৮০০টি অনুরোধ সামলায়। নিরাপত্তার জন্য একে ৭০%-এর বেশি ব্যস্ত রাখতে চান না। প্রতি DAU দিনে গড়ে ৩০টি অনুরোধ পাঠান, আর peak factor ৪. কত DAU পর্যন্ত একটি সার্ভার যথেষ্ট? তার আগেই দুটি সার্ভার রাখা কেন যুক্তিসংগত হতে পারে?

    ব্যবহারযোগ্য ক্ষমতা = ৮০০ × ০.৭ = ৫৬০ অনুরোধ/সেকেন্ড। প্রতি DAU-র peak ভার = ৩০ × ৪ ÷ ৮৬,৪০০ = ১/৭২০ অনুরোধ/সেকেন্ড। তাই সর্বোচ্চ DAU = ৫৬০ × ৭২০ = ৪,০৩,২০০ — মোটামুটি ৪ লাখ।

    খাতায় এভাবে লিখুন: peak = DAU × ৩০ × ৪ ÷ ৮৬,৪০০ = DAU ÷ ৭২০; শর্ত peak ≤ ৫৬০, তাই DAU ≤ ৪,০৩,২০০.

    কিন্তু availability-র প্রশ্নও আছে: একটি সার্ভার মানে একটি SPOF — OS হালনাগাদ বা disk নষ্ট হলেই সেবা বন্ধ। তাই অনেক কম DAU-তেও দুটি সার্ভার আর একটি load balancer প্রায়ই যুক্তিসংগত: খরচ বাড়ে, বন্ধ থাকার ঝুঁকি কমে। সিদ্ধান্ত নির্ভর করে সেবা বন্ধ থাকার দাম কত, তার ওপর (পর্ব ০৫)।

  3. নকশার সমালোচনা: একটি কাল্পনিক পরীক্ষার ফল প্রকাশের সাইট এভাবে চলে: একটি ভাড়া করা VPS-এ Nginx, PHP আর MySQL; ফলের PDF আর ছবি একই disk-এ; কোনো backup নেই; deploy হয় সরাসরি সার্ভারে ফাইল কপি করে। ফল প্রকাশের প্রথম ১০ মিনিটে প্রায় ১০ লাখ মানুষ আসবেন, প্রত্যেকে গড়ে ৫টি অনুরোধ পাঠাবেন। দুর্বলতাগুলো চিহ্নিত করুন, আর গুরুত্ব অনুযায়ী সাজিয়ে সমাধান প্রস্তাব করুন।

    আগে হিসাব: ১০ লাখ × ৫ ÷ ৬০০ সেকেন্ড ≈ ৮,৩৩৩ অনুরোধ/সেকেন্ড — একটি VPS-এর জন্য অনেক বেশি। দুর্বলতা আর অগ্রাধিকার:

    • ১. Backup নেই: হারানো ডেটা ফেরানো যায় না, তাই সবার আগে — অন্য জায়গায় স্বয়ংক্রিয় backup, আর restore করে পরীক্ষা।
    • ২. ডেটার স্বভাবই বড় সূত্র: প্রকাশের পর ফল আর বদলায় না, অর্থাৎ পুরোপুরি read-only. তাই প্রতিটি ফল আগেই স্থির ফাইল (HTML বা JSON) বানিয়ে object storage-এ রেখে CDN দিয়ে দেওয়া যায় — database-এ প্রায় কোনো অনুরোধই যাবে না। এটি cache-এরই চরম রূপ, আগেভাগে হিসাব করে রাখা।
    • ৩. সব কিছু এক সার্ভারে: SPOF — অন্তত দুটি app সার্ভার, load balancer আর database-এর একটি কপি।
    • ৪. PDF আর ছবি একই disk-এ: bandwidth আর disk শেষ করে; CDN আর object storage-এ সরান।
    • ৫. প্রকাশের মুহূর্তে সবাই একসাথে: CDN-এ ফাইল আগে থেকে পৌঁছে রাখা, অনুরোধের সীমা (rate limiting, পর্ব ৪৯), দরকারে অপেক্ষার সারি।
    • ৬. সরাসরি সার্ভারে deploy: আগের সংস্করণে ফেরার ব্যবস্থা রাখুন, আর বড় দিনের আগে load test করুন।

    সবচেয়ে বড় লাভ এলো বেশি সার্ভার থেকে নয়, ডেটার স্বভাব বোঝা থেকে।

  4. আউটপুট অনুমান করুন: অংশ ৪-এর growth ক্যালকুলেটরে শুধু REQ_PER_USER ৪০ থেকে কমিয়ে ১০ করা হলো, বাকি সব একই। চালানোর আগে অনুমান করুন — 1,000,000 আর 100,000,000 DAU-র সারিতে peak, apps আর likely stage কী দেখাবে? তারপর চালিয়ে মিলিয়ে নিন।

    অনুরোধ চার ভাগের এক ভাগ, তাই প্রতিটি QPS-ও চার ভাগের এক ভাগ।

    • 1,000,000: peak = ১,৩৮৮.৯ ÷ ৪ = ৩৪৭.২ — এক বাক্সের সীমা ১০০-র ওপরে, কিন্তু একটি app সার্ভারের ৫০০-র নিচে। তাই apps ১, ধাপ ২।
    • 100,000,000: peak = ৩৪,৭২২.২; apps = ৭০. DB query = ৬৯,৪৪৪/s; তার ৫% লেখা = ৩,৪৭২/s — একটি primary-র ৫,০০০-এর মধ্যে, তাই sharding লাগছে না। Cache-এর পরে read বাকি থাকে ৬৫,৯৭২ × ০.১ ≈ ৬,৫৯৭/s, লেখা মিলিয়ে ১০,০৬৯/s — এক DB-র সাধ্যের বাইরে। তাই ধাপ ৫, আর ৬,৫৯৭ ÷ ৫,০০০ থেকে ২টি replica (ক্যালকুলেটরের সরল হিসাবে; replica-তে প্রতিটি লেখা প্রয়োগের খরচ ধরলে আরও বেশি)।

    আসল আউটপুটের এই দুটি লাইন:

    1,000,000      115.7    347.2     1  2 app server + separate DB
    100,000,000  11574.1  34722.2    70  5 + read replicas (2)

    শিক্ষা: একটি অনুমান চার গুণ বদলালে architecture-এর সিদ্ধান্তই বদলায় — sharding-এর বদলে replica-ই যথেষ্ট। তাই নকশার আগে সংখ্যাগুলো মাপা এত জরুরি।

নিজেকে যাচাই করুন

ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।

ক্রমক্লাসিক গল্পে একটি অ্যাপ যে ক্রমে বড় হয়, সেভাবে সাজান (▲▼ চেপে সরান)

  1. 🖥️ একটি সার্ভারে app আর database একসাথে
  2. 🗄️ Database আলাদা সার্ভারে
  3. ⚖️ Load balancer আর কয়েকটি stateless app সার্ভার
  4. ⚡ Database-এর সামনে cache
  5. 📚 Read replica দিয়ে পড়ার ভাগ
  6. 🧩 Sharding দিয়ে ডেটা আর লেখার ভাগ

একটি ride-sharing সেবায় কোন সার্ভিস চালকদের location নেবে, তা কোন database-এ থাকবে, আর কোন অংশ যাত্রী-চালকের মিল করবে — এই সিদ্ধান্তগুলো কোন ধরনের নকশার অংশ?

  • Low-level design — class আর method-এর নকশা
  • High-level design — পুরো সেবার উপাদান, সংযোগ আর ডেটার পথ
  • UI design — স্ক্রিনের নকশা
  • Database normalization

একটি অ্যাপের একমাত্র database-এর CPU সারাক্ষণ ৯৫%, অথচ app সার্ভারগুলোর CPU ৩০%. মাপজোখে দেখা গেল ৯০% query একই কয়েকশো পণ্যের তথ্য বারবার পড়ছে। সবচেয়ে সরাসরি প্রথম পদক্ষেপ কোনটি?

  • আরও app সার্ভার যোগ করা
  • সঙ্গে সঙ্গে database sharding করা
  • জনপ্রিয় তথ্যের জন্য database-এর সামনে cache বসানো
  • পণ্যের ছবিগুলো CDN-এ সরানো

একটি অ্যাপের DAU ২০ লাখ, প্রত্যেকে দিনে গড়ে ৪৩.২টি অনুরোধ পাঠান, আর peak factor ৩. Peak QPS কত?

  • ১,০০০
  • ৭২,০০০
  • ৮,৬৪,০০,০০০
  • ৩,০০০

Load balancer-এর পেছনে একই app-এর অনেকগুলো সার্ভার রাখতে হলে ব্যবহারকারীর লগইন session কোথায় রাখা উচিত?

  • সব সার্ভার পড়তে পারে এমন একটি shared store-এ (যেমন cache বা database), অথবা client-এর কাছে signed token-এ
  • যে সার্ভার লগইন নিয়েছে, শুধু তার মেমরিতে
  • Load balancer-এর log ফাইলে
  • CDN-এ

একটি সেবায় আছে ১টি load balancer, ৩টি app সার্ভার আর ১টি database (কোনো replica নেই)। কোন অংশগুলো single point of failure?

  • শুধু app সার্ভারগুলো
  • শুধু database
  • Load balancer আর database দুটোই
  • কোনোটিই নয়, কারণ সার্ভার তিনটি

Peak-এ সেকেন্ডে ১০,০০০টি read আসে, আর cache-এর hit ratio ৯৫%. Database-এ সেকেন্ডে কতগুলো read পৌঁছায়?

  • ৯,৫০০
  • ৫০০
  • ৯৫
  • ১,০০০

শব্দকোষ

লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:

মনে রাখুন

  1. System design = পুরো সেবার উপাদান, সংযোগ, ডেটার পথ আর ব্যর্থতায় আচরণ; এই কোর্স high-level design নিয়ে।
  2. পাঁচটি চাপ — scale, reliability, latency, খরচ, বদলানোর ক্ষমতা; একসাথে সবকটি সর্বোচ্চ হয় না।
  3. ক্লাসিক ক্রম: একটি সার্ভার → আলাদা DB → LB + stateless app → cache → replica → CDN → queue → sharding → বহু region; সমস্যা আগে, সমাধান পরে।
  4. গড় QPS = DAU × দৈনিক অনুরোধ ÷ ৮৬,৪০০; peak = গড় × peak factor; database-এ পৌঁছায় শুধু cache miss.
  5. প্রতিটি বাক্সে জিজ্ঞেস করুন “এটি মরলে?”; প্রতিটি সিদ্ধান্তের দাম লিখে রাখুন; AI-এর নকশা হিসাব আর ব্যর্থতার প্রশ্নে যাচাই করুন।

পরের পর্বে: নকশা শুরু হয় প্রশ্ন দিয়ে, বাক্স দিয়ে নয়। কী বানাতে হবে (functional requirement), কতটা ভালোভাবে (non-functional — latency, availability, consistency), আর ভালো নকশার মাপকাঠি দিয়ে trade-off কীভাবে মাপবেন।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

এই পর্বটি শেয়ার করুন:
এই পর্বে ভুল পেয়েছেন? জানান