এই পর্বে যা শিখবেন
- যেকোনো ধারণার প্রশ্নকে একটি trade-off হিসেবে বলা — কী পাই, কী দিই, কোন অবস্থায় কোন দিক জেতে, আর একটি সংখ্যা দিয়ে
- Latency, availability, API, scaling, caching আর ডেটাবেসের প্রশ্নে follow-up-এর শিকল ধরে গভীরে নামা
- Messaging, CAP-PACELC, quorum, consensus, ঘড়ি, fencing token আর CRDT-র প্রশ্নে সংজ্ঞার ভুল এড়িয়ে সঠিক দাবি করা
- Resilience, rate limiting, SLO, DR, deployment আর নিরাপত্তার প্রশ্নে বাস্তব পরিচালনার দৃষ্টিভঙ্গি দেখানো
- ইন্টারভিউর আচরণ: প্রশ্ন পরিষ্কার করা, আপত্তি সামলানো, না জানলে সৎভাবে বলা — আর red flag বাক্যগুলো চিনে এড়ানো
১ · ধারণার প্রশ্নে ইন্টারভিউয়ার কী শোনেন — তিন স্তর আর উত্তরের ছক
System design ইন্টারভিউর একটি বড় অংশ পুরো নকশা নয়, ছোট ধারণার প্রশ্ন: “cache-aside আর write-through-এর পার্থক্য কী?”, “R + W > N হলেও পুরোনো মান আসে কেন?”, “retry-তে jitter কেন লাগে?”। এগুলো আসে নকশার মাঝখানে deep dive হিসেবে, বা আলাদা আলোচনায়। ইন্টারভিউয়ার সংজ্ঞা শুনতে চান না — শুনতে চান আপনি দামটা জানেন কি না। নিচের প্রশ্নগুলো এ ধরনের আলোচনায় প্রায়ই আসা ধাঁচের; কোনো নির্দিষ্ট প্রতিষ্ঠানের প্রশ্ন বা প্রক্রিয়া নয়, আর প্রতিষ্ঠানভেদে ধরন অনেক আলাদা।
| স্তর | সাধারণত যা শোনা হয় | কঠিনতার চিহ্ন |
|---|---|---|
| শুরু | সঠিক সংজ্ঞা, একটি সুবিধা আর একটি দাম, একটি সহজ উদাহরণ। “কোনটি কখন” বলতে পারা। | (সহজ) |
| মাঝারি | সংখ্যায় trade-off, ব্যর্থতার একটি ঘটনা, বাস্তব টুলের আচরণ — আর follow-up-এ এক-দুই স্তর নিচে নামা। | (মাঝারি) |
| অভিজ্ঞ | কোণার ঘটনা, ভুল ধারণা ভাঙা, পরিচালনার দাম (alert, migration, rollback), আর “কীভাবে যাচাই করব” — অনুমান নয়, মাপ। | (কঠিন) |
স্তরগুলো শুধু প্রস্তুতির সুবিধার জন্য। নতুন প্রকৌশলীর কাছেও অভিজ্ঞ-স্তরের প্রশ্ন আসতে পারে, আর সিনিয়রকেও শুরুর প্রশ্নে পরিষ্কার উত্তর দিতে হয়।
শক্তিশালী উত্তরের ছক
- প্রশ্ন পরিষ্কার করা (clarifying question): “পড়া বেশি না লেখা?”, “পুরোনো ডেটা কতক্ষণ চলে?” — বেশিরভাগ trade-off-এর উত্তর এই দুই প্রশ্নেই বদলে যায়।
- জোরে ভাবা (think aloud): অনুমান মুখে বলুন — “ধরছি একই data center, RTT প্রায় ০.৫ ms” — যাতে ইন্টারভিউয়ার ভুল অনুমান ধরিয়ে দিতে পারেন।
- সংখ্যা: একটি মোটা দাগের সংখ্যা বিশ্বাসযোগ্যতা অনেক বাড়ায়: “৯০% থেকে ৯৯% hit মানে ডেটাবেসে চাপ দশ গুণ কম।” বানানো নির্দিষ্ট সংখ্যার চেয়ে “মাত্রা এরকম” বলা ভালো।
- Follow-up-এর জন্য তৈরি থাকা (follow-up): প্রতিটি উত্তরের শেষ বাক্যই পরের প্রশ্ন ডেকে আনে। ইচ্ছা করে সেই দরজাটি খোলা রাখুন যেখানে আপনি গভীরে যেতে পারেন।
রেস্তোরাঁয় নতুন একজন ওয়েটারকে জিজ্ঞেস করুন “কোনটা ভালো?” — তিনি বলবেন “সবই ভালো”। অভিজ্ঞ ওয়েটার আগে জিজ্ঞেস করেন, “ঝাল চলে? কতজন? তাড়া আছে?” তারপর বলেন, “কাচ্চি ভালো, তবে সময় লাগবে ২৫ মিনিট; তাড়া থাকলে খিচুড়ি।” তিনি সুপারিশ করেছেন, দামও বলেছেন, আর বিকল্পও দিয়েছেন। ধারণার প্রশ্নে ভালো উত্তর ঠিক এমন: প্রশ্ন, সিদ্ধান্ত, দাম, বিকল্প।
নিচের ছবিতে একটি সাধারণ web সেবার বাক্সগুলো, আর কোন বাক্স নিয়ে প্রশ্ন এই পাতার কোন অংশে। ইন্টারভিউর মাঝে যে বাক্সে আলোচনা পৌঁছায়, সেখানকার প্রশ্নগুলোই সাধারণত আসে।
একটি সাধারণ web সেবা — কোন বাক্সের প্রশ্ন কোন অংশে
Request path from client to data, with the section of this page that covers each box
সবচেয়ে বেশি চোখে পড়া ভুল: প্রশ্ন শেষ হওয়ার আগেই টুলের নাম বলা (“Kafka দিয়ে করব”); “সবসময়” আর “কখনো না” দিয়ে উত্তর; ACID-এর C আর CAP-এর C গুলিয়ে ফেলা; আর বানানো নির্দিষ্ট সংখ্যা আত্মবিশ্বাসের সাথে বলা। “নিশ্চিত নই, তবে মাত্রা এরকম, আর এভাবে মেপে দেখব” — এটি দুর্বলতা নয়, পরিণত বিচারের চিহ্ন।
২ · ভিত্তি আর হিসাবের অনুভূতি — latency, percentile, availability আর মাথায় QPS
রিভিশন: পর্ব ১ · System design কী, পর্ব ২ · Requirement আর trade-off, পর্ব ৩ · Back-of-the-envelope হিসাব, পর্ব ৪ · Latency আর percentile, পর্ব ৫ · Availability, পর্ব ৬ · নকশার কাঠামো। পূর্ণ সমাধানের হিসাব পর্ব ৬২-এ।
প্র ০১শুরু · Latency আর throughput কি একই জিনিসের দুই নাম? একটি ভালো করতে গিয়ে অন্যটি খারাপ হয় কখন? (সহজ)
শক্তিশালী উত্তর: না। Latency হলো একটি অনুরোধে কত সময়; throughput হলো প্রতি সেকেন্ডে কতগুলো কাজ শেষ। Batching-এ দুটি উল্টো দিকে যায়: ডেটাবেস ১০ ms ধরে commit জমিয়ে একটি fsync-এ লিখলে (group commit) সেকেন্ডে অনেক বেশি commit হয়, কিন্তু প্রতিটি commit বড়জোর ১০ ms বেশি অপেক্ষা করে। উল্টো দিকে, latency একই রেখে একসাথে বেশি কাজ চালালে throughput বাড়ে — যতক্ষণ না কোনো ধাপ bottleneck হয়। কোনটি আগে, তা ঠিক করে requirement: ব্যবহারকারীর সামনের অনুরোধে p99 latency, রাতের batch কাজে throughput.
দুর্বল উত্তর দেখতে যেমন: “throughput বাড়লে latency এমনিই কমে।” — Queue ভরা সার্ভারে উল্টোটাই ঘটে।
ফলো-আপ:
- “Bandwidth আর throughput কি এক?” → না; bandwidth পথের সর্বোচ্চ ক্ষমতা, throughput আসলে যতটা বইছে।
- “Batch-এর আকার কীভাবে ঠিক করবেন?” → দুটি সীমা একসাথে: সর্বোচ্চ আকার আর সর্বোচ্চ অপেক্ষা — যেটি আগে পূরণ হয়।
প্র ০২শুরু · Dashboard বলছে গড় response time ৮০ ms. এটি কি ভালো খবর? (সহজ)
শক্তিশালী উত্তর: গড় লেজ লুকায়। ধরা যাক ৯৯% অনুরোধ ৫০ ms-এ, ১% লাগে ৩ সেকেন্ড: গড় = ০.৯৯ × ৫০ + ০.০১ × ৩০০০ = ৭৯.৫ ms — “সুন্দর” সংখ্যা, অথচ প্রতি ১০০টি অনুরোধে একটি ৩ সেকেন্ড আটকে। যিনি দিনে শত অনুরোধ করেন, তিনি প্রায় নিশ্চিতভাবে সেই লেজে পড়বেন। তাই histogram থেকে percentile — p50, p99, p99.9 — আর লক্ষ্য লিখুন সেভাবে: “p99 ৩০০ ms-এর কম”।
ফলো-আপ:
- “তিন সার্ভারের p99-এর গড় নিলে মোট p99?” → না, percentile-এর গড় হয় না; histogram-এর bucket যোগ করে তারপর percentile (পর্ব ৫০)।
- “Load test-এ p99 ভালো, production-এ খারাপ কেন?” → প্রায়ই coordinated omission: load generator ধীর উত্তরের অপেক্ষায় পরের অনুরোধ পাঠায় না, তাই ধীর সময়টাই কম মাপা হয়; সাথে ঠান্ডা cache আর ছোট test ডেটা।
প্র ০৩মাঝারি · একটি search অনুরোধ ১০০টি shard-এর উত্তরের অপেক্ষা করে। প্রতিটি shard মাত্র ১% সময় ধীর। ব্যবহারকারী কত ঘনঘন ধীর উত্তর পাবেন, আর কী করবেন? (মাঝারি)
শক্তিশালী উত্তর: অনুরোধ ধীর হয় যদি অন্তত একটি shard ধীর: ১ − (১ − p)N = ১ − ০.৯৯১০০ ≈ ৬৩.৪%. “বিরল” ১% fan-out-এ সাধারণ ঘটনা হয়ে যায় — tail latency-ই অনুরোধের সময় ঠিক করে। প্রতিকার: (১) hedged request — একটি shard ধরা যাক p95 সময় পেরিয়েও চুপ থাকলে আরেকটি replica-তে একই অনুরোধ; (২) fan-out কমানো — বড় shard বা আগে জোড়া ফল; (৩) deadline-এ যা এসেছে তা দিয়ে আংশিক উত্তর, যেখানে তা চলে। নিচের ছোট simulator সংখ্যাটি মিলিয়ে দেখায়।
দুর্বল উত্তর দেখতে যেমন: “প্রতিটি shard তো ৯৯% দ্রুত, তাই অনুরোধও প্রায় ৯৯% দ্রুত।”
ফলো-আপ:
- “Hedge কি সবসময় ভালো?” → না; বাড়তি ভার আনে। Overload-এ বন্ধ রাখতে হয়, আর শুধু idempotent পড়ায়।
- “আংশিক উত্তর কোথায় চলে না?” → টাকার হিসাব বা সিটের তালিকায়; search বা feed-এ প্রায়ই চলে।
// Fan-out tail: a request waits for ALL N leaf calls. Each leaf is "slow" with probability p.
// Closed form: P(at least one slow) = 1 - (1 - p)^N. Seeded simulation checks the formula.
// Hedging: if a leaf is slow, a second copy is sent; the leaf stays slow only if BOTH are slow
// (assumes the two copies are independent), so per-leaf slowness becomes p * p.
function mulberry32(a) { return () => { a = (a + 0x6D2B79F5) | 0; let t = Math.imul(a ^ (a >>> 15), 1 | a);
t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t; return ((t ^ (t >>> 14)) >>> 0) / 4294967296; }; }
const rnd = mulberry32(42), TRIALS = 20000;
function simulate(N, p, hedge) {
let slowReq = 0;
for (let t = 0; t < TRIALS; t++) {
let slow = false;
for (let i = 0; i < N && !slow; i++) {
const a = rnd() < p, b = hedge ? rnd() < p : true;
if (a && b) slow = true;
}
if (slow) slowReq++;
}
return (100 * slowReq / TRIALS).toFixed(2);
}
console.log(" N p formula % sim % hedged formula % hedged sim %");
for (const N of [1, 10, 100]) for (const p of [0.01, 0.001]) {
const f = (100 * (1 - (1 - p) ** N)).toFixed(2), fh = (100 * (1 - (1 - p * p) ** N)).toFixed(4);
console.log(String(N).padStart(4) + String(p).padStart(7) + f.padStart(12) + simulate(N, p, false).padStart(8) +
fh.padStart(19) + simulate(N, p, true).padStart(15));
}আউটপুট:
N p formula % sim % hedged formula % hedged sim %
1 0.01 1.00 0.91 0.0100 0.01
1 0.001 0.10 0.08 0.0001 0.00
10 0.01 9.56 9.57 0.1000 0.11
10 0.001 1.00 1.04 0.0010 0.00
100 0.01 63.40 63.34 0.9951 1.09
100 0.001 9.52 9.63 0.0100 0.01
Seed-দেওয়া simulation সূত্রের সাথে মেলে: N = ১০০, p = ০.০১-এ সূত্র ৬৩.৪০%, simulation ৬৩.৩৪%. Hedge-এর পরে একটি shard ধীর থাকে শুধু দুটি কপিই ধীর হলে, অর্থাৎ p² = ০.০০০১ — তখন ১০০টির fan-out-এও মাত্র প্রায় ১%. দাম: যত অনুরোধ hedge হয় তত বাড়তি কাজ; p95-এ hedge করলে প্রায় ৫%. শর্তটিও লক্ষ করুন — দুই কপির ধীরতা স্বাধীন ধরা হয়েছে। দুটি replica একই কারণে ধীর হলে (একই hot key, একই GC-ঝড়), লাভ অনেক কম।
প্র ০৪মাঝারি · সার্ভারগুলো ৯০% CPU-তে চলছে — খরচের দিক থেকে তো দারুণ দক্ষতা, তাই না? (মাঝারি)
শক্তিশালী উত্তর: Latency-র দিক থেকে বিপজ্জনক। সরল M/M/1 মডেলে গড় সময় = S ÷ (১ − ρ): ρ = ০.৫-এ ২S, ০.৮-এ ৫S, ০.৯-এ ১০S, ০.৯৫-এ ২০S. ৫০% থেকে ৯০%-এ গড় সময় পাঁচ গুণ, আর লেজ আরও বেশি। তার ওপর একটি instance মরলে বাকিদের ভার বাড়ে: ৪টির একটি গেলে বাকি তিনটিতে ৪/৩ গুণ — ৯০% হয়ে যায় ১২০%, queue অসীমের দিকে। তাই ব্যবহারকারীর সামনের সেবায় লক্ষ্য utilization সাধারণত মাঝামাঝি, যাতে N + ১ আর হঠাৎ ভিড় সামলানো যায়। রাতের batch কাজে ৯০% ঠিকই আছে — সেখানে লক্ষ্য throughput.
ফলো-আপ:
- “M/M/1 কি বাস্তবে খাটে?” → অনুমানগুলো (Poisson আগমন, exponential সেবা) কাঁচা; কিন্তু “হাঁটু”-র আকৃতি সত্য। আসল হাঁটু load test দিয়ে খুঁজুন।
- “CPU ছাড়া আর কী দেখবেন?” → queue-র দৈর্ঘ্য, connection pool আর thread pool-এর ব্যস্ততা — এগুলো আগে ভরে।
প্র ০৫মাঝারি · প্রতিটি সার্ভিস ৯৯.৯% available. তাহলে পুরো সিস্টেমও ৯৯.৯%? (মাঝারি)
শক্তিশালী উত্তর: নির্ভর করে তারা পরপর (series) না পাশাপাশি (parallel). একটি অনুরোধ যদি ২০টি সার্ভিসের সবাইকে চায়, availability গুণ হয়: ০.৯৯৯২০ ≈ ৯৮.০২% — বছরে কয়েক দিনের সমান downtime. দুটি স্বাধীন ৯৯% কপি পাশাপাশি থাকলে ব্যর্থতার গুণ: ১ − ০.০১² = ৯৯.৯৯%. শর্ত “স্বাধীন”: একই config push, একই bug, একই rack বা region সব কপিকে একসাথে ফেলে — correlated failure. তুলনার জন্য: ৯৯.৯% মানে ৩৬৫ দিনের বছরে প্রায় ৮ ঘণ্টা ৪৫ মিনিট।
দুর্বল উত্তর দেখতে যেমন: “সব সার্ভিসের দুটি করে কপি দিলেই ৯৯.৯৯%.” — failover-এর সময় আর একই ধরনের ব্যর্থতা হিসাবের বাইরে।
ফলো-আপ:
- “Series-এর ক্ষতি কমাবেন কীভাবে?” → অনুরোধের পথে কম dependency, কিছু কাজ queue দিয়ে পথের বাইরে, আর graceful degradation — recommendation বন্ধ হলে সাধারণ তালিকা।
- “Parallel-এর লাভ কে খায়?” → বিকলতা ধরতে আর failover করতে যে সময় লাগে, আর failover নিজেই যে মাঝে মাঝে ব্যর্থ হয়।
প্র ০৬শুরু · “১ কোটি দৈনিক ব্যবহারকারী” শুনে মাথায় প্রথম কোন সংখ্যা আসা উচিত, আর তা নকশা কীভাবে বদলায়? (সহজ)
শক্তিশালী উত্তর: প্রতি সেকেন্ডে অনুরোধ। ধরা যাক জনপ্রতি দিনে ২০টি অনুরোধ: ১ কোটি × ২০ ÷ ৮৬,৪০০ ≈ ২,৩১৫ QPS গড়; peak গড়ের ৩ গুণ ধরলে প্রায় ৬,৯৪৪ — মাথায় “দিন ≈ ১০৫ সেকেন্ড” ধরলে ২,০০০ আর ৬,০০০, একই মাত্রা। অর্থাৎ কয়েক হাজার QPS: কয়েকটি stateless app সার্ভার, সামনে cache, আর পড়ার জন্য read replica-সহ একটি ভালো database সাধারণত যথেষ্ট; sharding এখনই নয়। সংখ্যাটি নির্ভুল হওয়া জরুরি নয় — মাত্রাটি সিদ্ধান্ত বদলায়।
দুর্বল উত্তর দেখতে যেমন: “এক কোটি ব্যবহারকারী, তাই microservices, Kafka আর sharding লাগবে।” — কোনো হিসাব ছাড়াই বড় নকশা।
ফলো-আপ:
- “জনপ্রতি ২০টি কোথা থেকে?” → অনুমান — আগেই মুখে বলুন, ইন্টারভিউয়ার বদলাতে পারেন।
- “লেখা কতগুলো?” → read:write ধরা যাক ১০:১ হলে গড় প্রায় ২১০টি লেখা/সেকেন্ড; লেখার চাপই সাধারণত shard-এর প্রশ্ন আনে।
প্র ০৭অভিজ্ঞ · Availability বাড়াতে বাজেট কোথায় দেবেন — কম ভাঙা (MTBF বাড়ানো), নাকি দ্রুত সারানো (MTTR কমানো)? (কঠিন)
শক্তিশালী উত্তর: A = MTBF ÷ (MTBF + MTTR). MTBF ১,০০০ ঘণ্টা, MTTR ১ ঘণ্টা হলে ৯৯.৯০%; MTTR অর্ধেক করলে ৯৯.৯৫% — যা MTBF দ্বিগুণ করারও ফল। গাণিতিকভাবে সমান, কিন্তু খরচে নয়: দ্রুত টের পাওয়া (MTTD), এক ক্লিকে rollback, feature flag আর runbook প্রায়ই অনেক সস্তা, আর সব ব্যর্থতা ঠেকানোও যায় না। তাই প্রায়ই আগে MTTR. ব্যতিক্রম যেখানে একটি ব্যর্থতাই অপূরণীয় — ডেটা হারানো, টাকা দুবার কাটা — সেখানে প্রতিরোধ, অর্থাৎ MTBF আর durability.
ফলো-আপ:
- “MTTR-এর মধ্যে সবচেয়ে বড় অংশ কোনটি?” → প্রায়ই টের পেতে আর কারণ খুঁজতে যাওয়া সময়; তাই লক্ষণভিত্তিক alert আর সাম্প্রতিক পরিবর্তনের তালিকা।
- “Blast radius কমানো কোন দিকে পড়ে?” → কোনোটিতে নয়, তৃতীয় হাতিয়ার — canary আর cell দিয়ে একটি ব্যর্থতায় কম মানুষ ক্ষতিগ্রস্ত।
৩ · API আর যোগাযোগ — idempotency, pagination, API-র ধরন, real-time আর schema
রিভিশন: পর্ব ৭ · Networking, পর্ব ৮ · REST API নকশা, পর্ব ৯ · gRPC আর GraphQL, পর্ব ১০ · Real-time যোগাযোগ, পর্ব ১১ · API gateway, পর্ব ১২ · Serialization আর schema
প্র ০৮শুরু · PUT আর POST-এর মধ্যে কোনটি idempotent? একটি payment API-তে এর বাস্তব মানে কী? (সহজ)
শক্তিশালী উত্তর: Idempotent মানে একই অনুরোধ একাধিকবার পাঠালে ফল একবার পাঠানোর মতোই। সংজ্ঞায় GET, PUT আর DELETE idempotent, POST নয়। টাকা কাটার POST-এ timeout হলে client জানে না কাটা হয়েছে কি না; আবার পাঠালে দুবার কাটতে পারে, না পাঠালে লেনদেন হারাতে পারে। সমাধান: client প্রতিটি কাজে একটি Idempotency-Key দেয়; সার্ভার key আর ফল একই transaction-এ রাখে, unique constraint-সহ। একই key-তে আগের উত্তর ফেরত, একই key-তে ভিন্ন body এলে 422 (পর্ব ৮)।
দুর্বল উত্তর দেখতে যেমন: “POST-এ কখনো retry করব না।” — তখন প্রতিটি timeout একটি হারানো বা অনিশ্চিত লেনদেন।
ফলো-আপ:
- “একই key নিয়ে দুটি অনুরোধ একসাথে এলে?” → প্রথমটি key-এর সারি “চলছে” অবস্থায় বসায়; দ্বিতীয়টি unique constraint-এ আটকে 409 পায় বা অপেক্ষা করে।
- “Key কতদিন রাখবেন?” → সম্ভাব্য retry-এর সময়ের চেয়ে বেশি — ঘণ্টা থেকে দিন; তারপর TTL দিয়ে মোছা।
প্র ০৯মাঝারি · একটি বড় তালিকার API-তে offset pagination না cursor? (মাঝারি)
শক্তিশালী উত্তর: OFFSET 100000 LIMIT 20-এ database-কে ১,০০,০২০টি সারি হেঁটে ২০টি দিতে হয় — গভীর পাতা ধীর; আর পড়ার মাঝে নতুন সারি এলে একটি সারি দুবার আসে বা বাদ পড়ে। Cursor বা keyset-এ শেষ দেখা সারি থেকে index ধরে পরের ২০টি — যেকোনো গভীরতায় একই খরচ, আর তালিকা বদলালেও স্থির। দাম: “পাতা ৫৭-এ লাফ” নেই, মোট সংখ্যা দেখানো আলাদা খরচ, sort বদলালে cursor-ও বদলায়। কখন offset: ছোট admin তালিকা, যেখানে পাতার নম্বর জরুরি।
ফলো-আপ:
- “Cursor-এ শুধু created_at কেন নয়?” → একই সময়ের দুই সারি আলাদা করতে id-ও লাগে — (created_at, id) জোড়া।
- “Cursor client-কে কীভাবে দেবেন?” → একটি অস্বচ্ছ string; ভেতরের গঠন পরে বদলানো যায়, আর client নিজে বানাতে পারে না।
প্র ১০মাঝারি · REST, gRPC না GraphQL — কখন কোনটি জেতে? (মাঝারি)
শক্তিশালী উত্তর: প্রশ্নটি “কোনটি ভালো” নয়, “client কারা”। বাইরের পাবলিক API-তে REST: HTTP caching, সব ভাষায় সহজ, সবাই বোঝে। ভেতরের সার্ভিস-থেকে-সার্ভিসে gRPC: .proto চুক্তি থেকে কোড, ছোট binary, HTTP/2 stream, deadline আর cancellation. মোবাইলের একটি পাতায় অনেক সার্ভিসের ডেটা লাগলে GraphQL বা একটি BFF — এক round trip-এ ঠিক যতটুকু দরকার। দাম: gRPC ব্রাউজারে সরাসরি চলে না আর L4 load balancer-এ দীর্ঘ সংযোগ ভার অসম করে; GraphQL-এ N+1 query, কঠিন HTTP caching আর খরচের সীমা টানার দায়।
দুর্বল উত্তর দেখতে যেমন: “gRPC দ্রুত, তাই সবখানে gRPC.”
ফলো-আপ:
- “একটি ভারী GraphQL query সার্ভার ডুবাতে পারে?” → পারে; depth limit, query-র খরচ হিসাব আর persisted query দিয়ে সীমা।
- “BFF আর GraphQL কি একই সমস্যার উত্তর?” → অনেকটা; BFF সরল কোড, GraphQL নমনীয় কিন্তু নিজের পরিকাঠামো চায়।
প্র ১১মাঝারি · Live score বা notification দেখাতে polling, long polling, SSE না WebSocket? (মাঝারি)
শক্তিশালী উত্তর: Short polling সহজ কিন্তু দামি: বিরতি I হলে গড় দেরি I/২, অনুরোধ N/I — ১ লাখ client প্রতি সেকেন্ডে poll করলে সেকেন্ডে ১ লাখ অনুরোধ, যার প্রায় সবই খালি। Long polling উত্তর আটকে রাখে, খালি উত্তর কমে। SSE এক দিকের স্থায়ী HTTP স্রোত, Last-Event-ID দিয়ে নিজেই ফাঁক পূরণ করে — live score আর notification-এ মানানসই। WebSocket দুই দিকের নালি — chat বা game; কিন্তু ack, resume আর ক্রম নিজেকে বানাতে হয়। সব স্থায়ী সংযোগের দাম একই: stateful gateway, প্রতি সংযোগে memory, আর deploy-এ সবার একসাথে ফেরা।
দুর্বল উত্তর দেখতে যেমন: “Real-time মানেই WebSocket.”
ফলো-আপ:
- “Gateway restart-এ কী হয়?” → হাজারো client একই মুহূর্তে reconnect — reconnect storm; প্রতিকার backoff আর full jitter, আর সংযোগ ধাপে ধাপে drain.
- “App পটভূমিতে থাকলে?” → OS সংযোগ কেটে দেয়; platform push দিয়ে জাগিয়ে তারপর sync.
প্র ১২অভিজ্ঞ · Rolling deploy চলছে; নতুন সংস্করণ বার্তায় একটি field যোগ করেছে আর একটি সরিয়েছে। কী ভাঙতে পারে? (কঠিন)
শক্তিশালী উত্তর: Rolling deploy-এ পুরোনো আর নতুন কোড একসাথে চলে, rollback-এ উল্টো দিকেও। তাই দুটোই লাগে: backward (নতুন কোড পুরোনো ডেটা পড়ে) আর forward (পুরোনো কোড নতুন ডেটা পড়ে)। Default-সহ optional field যোগ নিরাপদ। যে field পুরোনো কোড চায় তা সরালে পুরোনো reader ভাঙে; Protobuf-এ মোছা field-এর নম্বর আবার ব্যবহার করলে পুরোনো ডেটা নতুন অর্থে পড়া হয় — নিঃশব্দ ভুল। Queue আর log-এ পুরোনো বার্তা দিন পরেও পড়া হতে পারে, তাই সময়ের হিসাবও লাগে। প্রতিকার: মোছা নম্বর reserved, CI-তে schema registry-র compatibility check, আর expand → migrate → contract.
ফলো-আপ:
- “Required field যোগ করলে?” → পুরোনো writer সেটি দেয় না, নতুন reader ব্যর্থ হয়; তাই optional আর default.
- “JSON-এ ID সংখ্যা হিসেবে পাঠালে?” → ২৫৩-এর বড় integer JavaScript-এ নিঃশব্দে বদলায়; ID পাঠান string হিসেবে।
প্র ১৩শুরু · নতুন একটি HTTPS সংযোগে প্রথম উত্তর আসতে কয়টি round trip লাগে, আর কেন তা নকশায় জরুরি? (সহজ)
শক্তিশালী উত্তর: TCP-র handshake ১, TLS 1.3 ১, অনুরোধ-উত্তর ১ — মোট ৩ RTT; TLS 1.2-এ ৪, QUIC-এ ২। RTT ১৫০ ms হলে শুধু এতেই ৪৫০ ms, সার্ভার কিছু করার আগেই। তাই keep-alive, connection pool আর HTTP/2-এর multiplexing দিয়ে সংযোগ বারবার ব্যবহার, আর CDN বা edge দিয়ে TLS ব্যবহারকারীর কাছে শেষ করা। দূরত্ব কোড দিয়ে কমে না: fibre-এ প্রতি ১০০ km-এ RTT অন্তত প্রায় ১ ms, তাই প্রায় ১২,৯০০ km দূরের region-এ অন্তত প্রায় ১২৯ ms.
ফলো-আপ:
- “0-RTT-এর ঝুঁকি?” → early data আবার পাঠানো (replay) যায়, তাই শুধু idempotent অনুরোধে।
- “Connection pool কত বড়?” → Little-এর সূত্রে: প্রতি সেকেন্ডে call × গড় সময়, সাথে কিছু বাড়তি।
৪ · Scaling, load balancing আর caching — stateless, consistent hashing, stale data আর stampede
রিভিশন: পর্ব ১৩ · Scaling, পর্ব ১৪ · Load balancing, পর্ব ১৫ · Session আর state, পর্ব ১৬ · Consistent hashing, পর্ব ১৭ · CDN, পর্ব ১৮ · Overload, পর্ব ২৮ · Caching কৌশল, পর্ব ২৯ · Eviction আর invalidation, পর্ব ৩০ · Distributed cache
প্র ১৪মাঝারি · L4 না L7 load balancer? আর algorithm — round robin, least connections না power of two choices? (মাঝারি)
শক্তিশালী উত্তর: L4 দেখে IP আর port; একটি সংযোগের পুরোটা একই backend-এ যায় — দ্রুত আর সস্তা। L7 HTTP পড়ে, প্রতিটি অনুরোধ আলাদা করে বাছে, path ধরে routing আর retry করে — বিনিময়ে TLS খোলা আর বেশি CPU. HTTP/2 বা gRPC-র দীর্ঘ সংযোগে L4 ভার অসমান করে, কারণ একটি সংযোগে হাজারো অনুরোধ। Algorithm: সমান সার্ভারে round robin যথেষ্ট; গতি অসমান হলে least connections অনেক ভালো (পর্ব ১৪-এর simulator-এ p99 প্রায় ১,৯৪৫ বনাম ১২৪ ms); অনেক load balancer আর পুরোনো তথ্যে power of two choices — এলোমেলো দুটি দেখে কম ব্যস্তটি — সবাই একই “সেরা” সার্ভারে ঝাঁপিয়ে পড়ে না।
ফলো-আপ:
- “একটি সার্ভার মরলে কতক্ষণ অনুরোধ যায়?” → প্রায় fall × interval + timeout; interval ২ সেকেন্ড, পরপর ৩টি ব্যর্থতা আর timeout ১ সেকেন্ড হলে ৭ সেকেন্ড পর্যন্ত — passive check আর retry দিয়ে কমানো।
- “Load balancer নিজে মরলে?” → জোড়া LB, virtual IP সরানো বা anycast; LB-ও একটি বাক্স।
প্র ১৫মাঝারি · লগইন রাখবেন sticky session-এ, shared session store-এ, না JWT-তে? (মাঝারি)
শক্তিশালী উত্তর: Sticky session সবচেয়ে সহজ, কিন্তু সার্ভারটি মরলে তার সব session হারায়, ভার অসম হয়, deploy যন্ত্রণার। Shared session store সাধারণ উত্তর: cookie-তে শুধু একটি এলোমেলো ID, তথ্য TTL-সহ store-এ; যেকোনো সার্ভার পড়ে, আর logout মানে একটি key মোছা — দাম প্রতি অনুরোধে একটি store-lookup আর store-এর নিজের HA. JWT store ছাড়াই যাচাই হয় — অনেক সেবা বা অঞ্চলে সুবিধা — কিন্তু ফেরত নেওয়া কঠিন: মেয়াদ না ফুরানো পর্যন্ত চুরি যাওয়া token চলে। তাই ছোট মেয়াদ, refresh token, আর জরুরি ক্ষেত্রে deny list.
দুর্বল উত্তর দেখতে যেমন: “JWT encrypted, তাই ভেতরে যা খুশি রাখা যায়।” — সাধারণ JWT-র payload শুধু Base64URL, যে কেউ পড়তে পারে।
ফলো-আপ:
- “Deny list রাখলে তো আবার store লাগল?” → হ্যাঁ, তবে ছোট — শুধু বাতিল token, মেয়াদ পর্যন্ত।
প্র ১৬মাঝারি · Cache সার্ভার ৪ থেকে ৫টি করবেন। hash(key) mod N-এ সমস্যা কী, আর consistent hashing কী বাঁচায় — কী বাঁচায় না? (মাঝারি)
শক্তিশালী উত্তর: mod N-এ N থেকে N + ১ করলে N/(N + ১) ভাগ key-এর ঠিকানা বদলায় — ৪ থেকে ৫-এ ৮০%; cache-এ তা মানে হঠাৎ প্রায় সব miss আর database-এ ঢল। Consistent hashing-এ সার্ভার আর key একই ring-এ; নতুন সার্ভার শুধু নিজের অংশটুকু নেয় — গড়ে ১/(N + ১), অর্থাৎ ২০%. অল্প সার্ভারে ring-এর ভাগ অসমান, তাই প্রতিটি সার্ভার অনেক virtual node হয়ে বসে। যা বাঁচায় না: এটি key-এর সংখ্যা সমান করে, অনুরোধের চাপ নয় — একটি hot key তবু একটি সার্ভারেই পড়ে।
ফলো-আপ:
- “Hot key-এর উপায়?” → অ্যাপের ভেতরে ছোট TTL-এর local cache, key-এর কয়েকটি কপি (key#1…key#k) ছড়িয়ে পড়া, আর একই key-এর অনুরোধ এক করা।
- “Ring ছাড়া বিকল্প?” → rendezvous hashing — প্রতিটি সার্ভারের score, সর্বোচ্চ জেতে; virtual node লাগে না, খরচ O(N).
প্র ১৭শুরু · Cache-aside, write-through আর write-behind — কোনটি কখন? (সহজ)
শক্তিশালী উত্তর: Cache-aside: app আগে cache দেখে, miss হলে database থেকে এনে বসায় — শুধু চাওয়া ডেটা cache-এ ওঠে, cache মরলেও সেবা চলে; সবচেয়ে প্রচলিত। Write-through: প্রতিটি লেখা cache আর database দুটিতেই — টাটকা, কিন্তু লেখা ধীর আর অনেক না-পড়া ডেটাও cache-এ। Write-behind: আগে cache, পরে batch-এ database — খুব দ্রুত লেখা, কিন্তু cache crash করলে লেখা হারায়; view counter-এর মতো ডেটায় চলে, টাকায় নয়। সংখ্যায় লাভ: cache ১ ms আর database ২০ ms ধরলে hit ৯০%-এ গড় ৩ ms, ৯৯%-এ ১.২ ms.
ফলো-আপ:
- “Wallet-এর balance cache থেকে দেখাবেন?” → দেখানো চলতে পারে, কিন্তু টাকা কাটার সিদ্ধান্ত কখনো cache থেকে নয় — database-এ শর্তসহ লেখা।
প্র ১৮অভিজ্ঞ · Cache-aside-এ ব্যবহারকারী মাঝে মাঝে পুরোনো দাম দেখছেন। কেন, আর কতটা গভীরে যাবেন? (কঠিন)
শক্তিশালী উত্তর: এটি আসলে একটি প্রশ্নের শিকল — প্রতিটি উত্তরের পরে ইন্টারভিউয়ার এক ধাপ নিচে নামেন। ছয়টি স্তর: (১) invalidation নেই, শুধু TTL; (২) delete আর commit-এর উল্টো ক্রম; (৩) commit-এর পরে delete করলেও stale set-এর race; (৪) delete বার্তাটাই হারানো; (৫) miss-এ পিছিয়ে থাকা replica থেকে পড়া; (৬) সব মিলিয়ে চূড়ান্ত নকশা। নিচের stepper প্রতিটি ধাপ সংখ্যাসহ দেখায়। শক্তিশালী উত্তরের চিহ্ন হলো প্রথম বাক্যেই “কতটা পুরোনো চলে?” জিজ্ঞেস করা — কয়েক সেকেন্ড চললে TTL আর delete যথেষ্ট, এক মুহূর্তও না চললে সেই পড়া cache থেকে নয়।
দুর্বল উত্তর দেখতে যেমন: “TTL ছোট করে দেব।” — Race-এর জানালা ছোট হয়, বন্ধ হয় না, আর database-এ চাপ বাড়ে।
- শুধু TTLলেখা cache জানে না
- উল্টো ক্রমআগে DEL, পরে COMMIT
- Stale setদেরিতে আসা SET
- হারানো DELcrash বা timeout
- Replica lagপুরোনো কপি থেকে ভরা
- চূড়ান্ত নকশাস্তরে স্তরে প্রতিরক্ষা
| ইন্টারভিউয়ারের প্রশ্ন | |
| ঘড়ি · DB · cache | |
| প্রতিকার | |
| দাম |
- শুধু TTL. লেখা যায় database-এ, cache-এর কপি তা জানে না। দাম ১০০ থেকে ১২০ হলো, অথচ cache-এর কপির TTL-এর ৩০০ সেকেন্ড বাকি — এই পুরো সময় সবাই ১০০ দেখবেন। প্রথম উত্তর: লেখার পরে key delete — পরের পাঠক miss করে নতুন মান আনবেন।
- উল্টো ক্রম. কেউ আগে delete করে তারপর database বদলান। ০ ms-এ DEL, ২ ms-এ একজন পাঠক miss করে database থেকে তখনো-পুরোনো ১০০ পড়ে বসালেন, ৩ ms-এ COMMIT ১২০. Cache আবার ১০০ — জানালাটি পুরো লেখার সময়জুড়ে। উত্তর: আগে COMMIT, তারপর DEL.
- Stale set. ক্রম ঠিক থাকলেও race বাকি। পাঠক A miss করে ১০০ পড়লেন, তারপর থেমে গেলেন — GC বা network-এর দেরি। ৩ ms-এ B-র COMMIT ১২০, ৪ ms-এ DEL — মোছার কিছু নেই। ৬০ ms-এ A SET ১০০ পাঠালেন। কোনো লেখা বাকি নেই যে মুছবে। উত্তর: miss-এ cache একটি lease token দেয়, DEL তা বাতিল করে, তাই A-র set প্রত্যাখ্যাত (পর্ব ২৮)।
- হারানো DEL. COMMIT হলো, তারপর app crash করল বা cache-এ পৌঁছাতে timeout — DEL কখনো গেল না। কোড নির্ভুল, তবু cache ১০০. উত্তর: app-এর বদলে database-এর commit log পড়ে delete পাঠানো (change data capture), retry-সহ; আর প্রতিটি key-তে TTL — যত বিরল race-ই হোক, ভুল কপি বড়জোর TTL পর্যন্ত টেকে।
- Replica lag. DEL ঠিকমতো পৌঁছাল, কিন্তু miss-এর পড়া গেল একটি read replica-তে, যা ৫০০ ms পিছিয়ে — সেখানে এখনো ১০০. সেটিই cache-এ বসল। উত্তর: cache ভরার পড়া primary থেকে, বা মানের সাথে version রেখে শুধু নতুনতর set গ্রহণ। Delayed double delete জানালা ছোট করে, বন্ধ করে না।
- চূড়ান্ত নকশা. স্তরে স্তরে: COMMIT-এর পরে DEL, CDC দিয়ে নিশ্চিত, lease বা version দিয়ে race বন্ধ, আর প্রতিটি key-তে TTL — সবচেয়ে খারাপ ক্ষেত্রেও staleness TTL-এর মধ্যে। শেষ বাক্যটি সবচেয়ে জরুরি: যে পড়ায় এক মুহূর্তও পুরোনো চলে না — balance থেকে টাকা কাটা, শেষ সিট — তা cache থেকে নয়।
প্র ১৯অভিজ্ঞ · একটি জনপ্রিয় key-এর মেয়াদ ফুরাতেই database-এর CPU লাফিয়ে উঠছে। কী ঘটছে, আর প্রতিকার কী? (কঠিন)
শক্তিশালী উত্তর: Cache stampede: মেয়াদ শেষে যত অনুরোধ আসে, recompute শেষ হওয়ার আগ পর্যন্ত সবাই miss করে database-এ যায়। Little-এর সূত্রে সংখ্যাটি সরল — সেকেন্ডে ২,০০০ অনুরোধ × ৫০ ms recompute = প্রায় ১০০টি একই query একসাথে। প্রতিকার: (১) single-flight — একটি lock বা lease, একজনই হিসাব করেন, বাকিরা অপেক্ষা করেন বা পুরোনো মান পান; (২) soft TTL বা stale-while-revalidate — মেয়াদ শেষেও পুরোনো মান দিয়ে পেছনে নবায়ন; (৩) মেয়াদের আগেই সম্ভাবনাভিত্তিক নবায়ন (XFetch); (৪) অনেক key একসাথে লেখা হলে TTL jitter — নইলে সবার মেয়াদ একই সেকেন্ডে।
ফলো-আপ:
- “অস্তিত্বহীন key-এর ঢল?” → ভিন্ন রোগ (penetration): “নেই” উত্তরটিই অল্প TTL-এ cache করা, বা সামনে Bloom filter.
- “Lock-ধারক মরে গেলে?” → lock-এর নিজের ছোট মেয়াদ; ধারক না ফিরলে পরের জন নেন।
প্র ২০অভিজ্ঞ · Hit ratio ৯০% থেকে ৯৯% করা কি শুধু ৯ শতাংশের উন্নতি? আর cache পুরো খালি হলে কী হবে? (কঠিন)
শক্তিশালী উত্তর: না — database দেখে miss, hit নয়। Database-এর ভার = মোট অনুরোধ × (১ − h): ১০% থেকে ১% মানে চাপ দশ গুণ কম। উল্টো পিঠ বিপজ্জনক: ৯৯% hit-এর সেবায় cache হারালে database-এ চাপ হঠাৎ ১০০ গুণ — যে database কখনো এত চাপ দেখেনি। তাই নকশায় প্রশ্ন: cache ঠান্ডা হলে কী? উত্তর হতে পারে replica-সহ cache, ধীরে গরম করা (ধাপে ধাপে traffic ঢোকানো), database-এর সামনে concurrency limit আর load shedding, আর জরুরি অবস্থায় কম-জরুরি feature বন্ধ। CDN-এর ক্ষেত্রেও একই অঙ্ক: ৯৯% hit-এর সাইটে CDN বিকল হলে origin-এ ১০০ গুণ।
ফলো-আপ:
- “৬টি cache shard-এর একটি মরলে?” → তার ভাগের hit মুহূর্তে miss; পর্ব ৩০-এর হিসাবে ৯৫% hit-এ database-এর চাপ ৪.১৭ গুণ — gutter pool বা replica সেই ধাক্কা নেয়।
প্র ২১অভিজ্ঞ · চাপ সামর্থ্যের দ্বিগুণ হলে সিস্টেম ধীরে না নেমে হঠাৎ ধসে পড়ে কেন? Queue বড় করলে কি সমাধান? (কঠিন)
শক্তিশালী উত্তর: চাপ সামর্থ্য ছাড়ালে queue লম্বা হয়, অপেক্ষা client-এর timeout ছাড়ায়, client আবার চেষ্টা করে — চাপ আরও বাড়ে। সার্ভার পুরো ব্যস্ত, অথচ সময়মতো সফল উত্তর — goodput — প্রায় শূন্য, কারণ সে এমন কাজ করছে যার অপেক্ষক আগেই চলে গেছে। বড় queue এটি আরও খারাপ করে: অসীম queue একটি bug. পর্ব ১৮-এর simulator-এ চাপ দ্বিগুণে bounded queue আর fail fast-এ goodput সেকেন্ডে প্রায় ১০০ থাকে, অসীম queue-তে নামে প্রায় ৬-এ। প্রতিকার: সীমিত queue, মেয়াদ-পেরোনো কাজ বাদ, দরজায় সস্তায় আর অগ্রাধিকার বুঝে 503 বা 429 (load shedding), ভেতরে backpressure, আর retry-কে বাজেটে বাঁধা।
ফলো-আপ:
- “চাপ কমে গেলেও সিস্টেম ফেরে না কেন?” → metastable failure: retry আর ঠান্ডা cache নিজেরাই চাপ টিকিয়ে রাখে; retry budget আর ধীরে traffic ফেরানো লাগে।
- “কাকে আগে ফেরাবেন?” → কম-জরুরি অনুরোধ (prefetch, analytics) আগে; লগইন আর payment শেষে।
৫ · ডেটাবেস — storage engine, index, replication, sharding আর transaction
রিভিশন: পর্ব ১৯ · Storage engine, পর্ব ২০ · SQL বনাম NoSQL, পর্ব ২১ · Index, পর্ব ২২ · Replication, পর্ব ২৩ · Sharding, পর্ব ২৪ · Isolation, পর্ব ২৫ · Distributed transaction, পর্ব ২৬ · Object storage, পর্ব ২৭ · Search, পর্ব ৫৪ আর পর্ব ৬০-এর case study
প্র ২২শুরু · নতুন একটি সেবার জন্য SQL না NoSQL? (সহজ)
শক্তিশালী উত্তর: প্রশ্নটিকে উল্টে দিন: কোন ডেটা, কোন প্রশ্নে কতবার পড়া-লেখা, আর কোন নিশ্চয়তা লাগে। Relational database দেয় schema, join, ACID transaction আর আগে না-ভাবা প্রশ্নেও উত্তর — টাকা, অর্ডার, সিটের মতো সম্পর্কভরা ডেটায় শক্ত শুরু। NoSQL-এর পরিবারগুলো নির্দিষ্ট access pattern-এ জেতে: key দিয়ে আনা-রাখা, বিশাল লেখার চাপ, সহজে ভাগ করা — বিনিময়ে প্রশ্ন ধরে আগে নকশা, ডেটার কপি আর join-এর অভাব। বেশিরভাগ সিস্টেমের সাধারণ শুরু একটি relational database আর একটি cache; বিশেষ store আসে মাপা প্রয়োজনে।
দুর্বল উত্তর দেখতে যেমন: “NoSQL scale করে, SQL করে না।” — SQL-ও replica আর sharding-এ বাড়ে; আর “schemaless” মানে schema কোডে চলে গেছে।
ফলো-আপ:
- “পণ্যের নাম দিয়ে search?” →
LIKE '%x%'নয়; আলাদা search engine-এ inverted index, primary database থেকে CDC দিয়ে হালনাগাদ — ফল একটু পিছিয়ে থাকে।
প্র ২৩মাঝারি · B-tree না LSM-tree — লেখা-ভারী আর পড়া-ভারী কাজে কোনটি, আর কেন? (মাঝারি)
শক্তিশালী উত্তর: B-tree জায়গায় বদলায়: প্রতিটি লেখা একটি random page বদল, পড়া অনুমানযোগ্য — fan-out ৫০০-র ৩ স্তরেই ১২.৫ কোটি key. LSM-tree জমিয়ে রাখে: memtable থেকে ক্রমিকভাবে SSTable, পেছনে compaction — লেখা দ্রুত, কিন্তু একটি পড়ায় কয়েক জায়গা দেখতে হতে পারে (Bloom filter সেটা কমায়), আর compaction CPU ও ডিস্ক খায়। তাই লেখা-ভারী (log, event, time-series) কাজে LSM প্রায়ই জেতে, পড়া-ভারী আর range-ভারী OLTP-তে B-tree. Read, write আর space amplification একসাথে কমানো যায় না — একটি কমালে অন্যটি বাড়ে।
ফলো-আপ:
- “LSM-এ মাঝে মাঝে লেখা থেমে যায় কেন?” → compaction পিছিয়ে পড়লে engine লেখা ধীর করে (write stall) — p99-এ ধরা পড়ে।
- “Analytics-এ কোনটি?” → দুটির কোনোটি নয় — column store; ৫০টির ২টি কলাম পড়লে ৪% byte.
প্র ২৪মাঝারি · Query: WHERE status = ? ORDER BY created_at DESC LIMIT 20. কোন index দেবেন, আর প্রতিটি index-এর দাম কী? (মাঝারি)
শক্তিশালী উত্তর: Composite index (status, created_at): সমতার কলাম আগে, sort বা range-এর কলাম পরে — index ঠিক সেই ক্রমেই সারি দেয়, sort লাগে না, ২০টি পেয়েই থামে। উল্টো ক্রম (created_at, status) এখানে কম কাজের, কারণ index কাজে লাগে বাঁ দিক থেকে মেলা অংশে — leftmost prefix. দরকারি সব কলাম index-এ থাকলে টেবিলে যেতেই হয় না (covering index). দাম: প্রতিটি INSERT আর UPDATE সব index হালনাগাদ করে — লেখা ধীর, জায়গা বাড়ে। আর অনুমান নয়: EXPLAIN দিয়ে plan দেখা।
ফলো-আপ:
- “status-এর মাত্র তিনটি মান, তবু index?” → একা status-এ selectivity কম; কিন্তু sort-এর সাথে জোড়ায় লাভ বড়।
- “Sharded টেবিলে এই query?” → status shard key না হলে সব shard-এ যায় (scatter-gather) — প্র ২৬।
প্র ২৫মাঝারি · ব্যবহারকারী প্রোফাইল বদলে সাথে সাথে রিফ্রেশ করলেন, পুরোনোটাই দেখছেন। কেন, আর replication sync না async? (মাঝারি)
শক্তিশালী উত্তর: লেখা গেছে leader-এ, পড়া গেছে একটি follower-এ যে এখনো পিছিয়ে — replication lag. প্রতিকার read-your-writes: লেখার কিছুক্ষণ পর পর্যন্ত সেই ব্যবহারকারীর পড়া leader-এ, বা client শেষ লেখার অবস্থান (LSN) মনে রেখে ততটা এগোনো replica বাছে। Sync বনাম async একটি দর-কষাকষি: async-এ commit দ্রুত, কিন্তু leader মরলে “OK” পাওয়া লেখাও হারাতে পারে; সব follower-এর ack চাইলে একটি follower বন্ধ হলেই লেখা আটকায়। মাঝের পথ semi-sync — অন্তত একটি follower-এর ack.
ফলো-আপ:
- “Replica বাড়ালে লেখার ক্ষমতা বাড়ে?” → না; replication পড়া বাড়ায়, লেখা নয় — প্রতিটি replica সব লেখাই করে।
- “Failover-এ সবচেয়ে বড় ঝুঁকি?” → পুরোনো leader জেগে উঠে লেখা নেওয়া — split brain; তাকে fencing করা লাগে (প্র ৩৮)।
প্র ২৬অভিজ্ঞ · একটি orders টেবিল shard করবেন। Shard key কী হবে, আর কোন ভুলগুলো পরে সবচেয়ে দামি? (কঠিন)
শক্তিশালী উত্তর: আগে সবচেয়ে ঘন query: “একজন ব্যবহারকারীর অর্ডার” হলে user_id — একজনের সব ডেটা এক shard-এ, query এক জায়গায়। চারটি শর্ত: অনেক ভিন্ন মান, সমান ছড়ানো, ঘন query এক shard-এ, আর বৃদ্ধিতেও টেকে। দামি ভুল: (১) created_at-এর মতো ক্রমিক key-এ range ভাগ — আজকের সব লেখা এক shard-এ (hot spot); (২) hash mod N — node বাড়ালে প্রায় সব সরে; বদলে node-এর চেয়ে অনেক বেশি নির্দিষ্ট partition (যেমন ২৫৬টি) বানিয়ে পুরো partition সরানো — ৪ থেকে ৫ node-এ সরে ৫১টি, প্রায় ২০%; (৩) shard key ছাড়া ঘন query — সব shard-এ scatter-gather, tail latency বাড়ে।
ফলো-আপ:
- “একজন বিক্রেতার লাখো অর্ডার?” → hot key: key-এ salt যোগ করে কয়েক ভাগে, পড়ায় মিলিয়ে নেওয়া।
- “কেন্দ্রীয় counter ছাড়া order ID?” → UUIDv7 বা Snowflake-ধাঁচ: প্রতি worker প্রতি ms-এ ৪,০৯৬টি, ৪১-bit সময়ে প্রায় ৬৯.৭ বছর; ঘড়ি পেছালে সাবধান।
প্র ২৭অভিজ্ঞ · Wallet থেকে দুটি অনুরোধ একসাথে ৮০০ আর ৬০০ টাকা তুলল, ব্যালান্স ছিল ১,০০০. দুটিই সফল। Database তো ACID — কীভাবে? (কঠিন)
শক্তিশালী উত্তর: App দুজনেই আগে পড়েছে ১,০০০, নিজে বিয়োগ করে লিখেছে — lost update. বহুল ব্যবহৃত ডিফল্ট READ COMMITTED এটি ঠেকায় না; ACID-এর I মানে “কোনো একটি isolation level”, সবসময় serializable নয়। হাতিয়ার, সরল থেকে কঠিন: শর্তসহ atomic UPDATE — SET balance = balance - 800 WHERE id = ? AND balance >= 800, প্রভাবিত সারি ০ হলে প্রত্যাখ্যান; SELECT … FOR UPDATE; version কলাম দিয়ে optimistic লেখা; বা SERIALIZABLE আর ব্যর্থ হলে পুরো transaction আবার। আরও সূক্ষ্ম রোগ write skew: দুজন দুটি আলাদা সারিতে লেখেন, নিয়মটি ভাঙে দুটি মিলিয়ে — snapshot isolation-এও ঘটে।
দুর্বল উত্তর দেখতে যেমন: “Transaction-এর ভেতরে রাখলেই হবে।”
ফলো-আপ:
- “PostgreSQL-এর REPEATABLE READ আর MySQL-এর একই নামের level কি এক?” → না; প্রথমটি আসলে snapshot isolation, দ্বিতীয়টির আচরণ আলাদা — নাম নয়, আচরণ যাচাই।
প্র ২৮অভিজ্ঞ · অর্ডার, পেমেন্ট আর স্টক তিনটি সেবার তিনটি database-এ। 2PC, saga না outbox? (কঠিন)
শক্তিশালী উত্তর: 2PC সত্যিকারের atomic commit দেয়, কিন্তু দামে: অতিরিক্ত round trip আর fsync, পুরো সময় lock, আর coordinator মরলে প্রস্তুত participant lock ধরে আটকে থাকে। একই সংস্থার কয়েকটি database-এ, কম লেনদেনে চলে; স্বাধীন microservice বা বাইরের payment provider-এ সাধারণত নয়। Saga: local transaction-এর শিকল, প্রতিটির একটি compensation — ব্যর্থ হলে উল্টো ক্রমে “ফেরত”। দাম: isolation নেই, তাই “স্টক ধরে রাখা” ধরনের pending অবস্থা লাগে। আর প্রতিটি ধাপে event পাঠাতে outbox: event আর ব্যবসার পরিবর্তন একই local transaction-এ, relay পরে পাঠায় — হারায় না, দুবার যেতে পারে, তাই consumer idempotent.
ফলো-আপ:
- “Compensation নিজেই ব্যর্থ হলে?” → retry করতে হয়, তাই compensation-ও idempotent; শেষে মানুষের হাতে যাওয়ার পথ।
- “Choreography না orchestration?” → ধাপ বেশি আর compensation জটিল হলে orchestrator — পুরো অবস্থা এক জায়গায় দেখা যায়।
প্র ২৯মাঝারি · ঈদের আগে বাসের টিকিটের ভিড়: একই সিট দুজন কিনছেন। Double booking কোথায় ঠেকাবেন? (মাঝারি)
শক্তিশালী উত্তর: সত্যের এক জায়গায় — seat database-এ শর্তসহ লেখা: UPDATE seats SET status = 'held', hold_until = ? WHERE id = ? AND status = 'available'; প্রভাবিত সারি ১ হলে আপনার, ০ হলে অন্য কেউ আগে পেয়েছেন। Hold-এর মেয়াদ থাকে, পেমেন্ট না হলে সিট ফেরে। Cache, app-এর memory বা শুধু একটি Redis lock সত্যের উৎস নয় — lock-এর মেয়াদ ফুরিয়ে দুজন ধারক হতে পারেন। ভিড় সামলানো আলাদা স্তরে: edge-এ virtual waiting room, যা database-এর সামর্থ্য বুঝে সেকেন্ডে নির্দিষ্ট সংখ্যক মানুষ ঢোকায়।
ফলো-আপ:
- “পেমেন্ট timeout হলো — টাকা কাটল কি না জানি না?” → payment-এর অবস্থায় UNKNOWN, একই idempotency key দিয়ে খোঁজ, আর দিনশেষে gateway-এর রিপোর্টের সাথে reconciliation.
প্র ৩০মাঝারি · ব্যবহারকারীর ছবি database-এর BLOB-এ রাখবেন, না object storage-এ? (মাঝারি)
শক্তিশালী উত্তর: Object storage-এ, আর database-এ শুধু metadata (key, আকার, মালিক, checksum). কারণ: ছবি বড় আর বদলায় না, database-এর buffer pool আর backup ভারী করে, আর object store সস্তায় প্রায় সীমাহীন বাড়ে। Upload-এ client সরাসরি store-এ যায় presigned URL দিয়ে — অল্প মেয়াদ, একটি key, একটি কাজ — app সার্ভার বিপুল byte বইতে বাধ্য নয়। পড়া যায় CDN দিয়ে। Store-এর ভেতরে দামের খেলা: ৩ কপি মানে ৩ গুণ জায়গা, RS(6,3) erasure coding-এ ১.৫ গুণ আর যেকোনো ৩টি টুকরো হারানো সয় — কিন্তু মেরামতে বেশি পড়া।
ফলো-আপ:
- “Upload সফল, কিন্তু metadata লেখার আগে app crash?” → orphan object; store-এর completion event থেকে metadata লেখা, আর lifecycle rule দিয়ে অসম্পূর্ণ upload মোছা।
- “ছবি নয়, ভিডিও হলে?” → খরচের কেন্দ্র সরে যায় বিতরণে (egress); পর্ব ৫৯-এর অনুমানে যত byte ঢোকে, তার প্রায় ৪৬৯ গুণ বেরোয় — তাই CDN আর adaptive bitrate.
৬ · Messaging, stream আর async — queue বনাম log, delivery, ক্রম আর সময়
রিভিশন: পর্ব ৩১ · Message queue, পর্ব ৩২ · Pub/sub, পর্ব ৩৩ · Log streaming, পর্ব ৩৪ · Delivery semantics, পর্ব ৩৫ · Event sourcing আর CQRS, পর্ব ৩৬ · Batch আর stream, পর্ব ৩৭ · Job আর workflow, আর পর্ব ৫৫, পর্ব ৫৬, পর্ব ৫৭-এর case study
প্র ৩১শুরু · অর্ডার হলে ইমেইল পাঠাতে সরাসরি call না message queue? Queue কখন ক্ষতি করে? (সহজ)
শক্তিশালী উত্তর: ইমেইল ধীর আর বাইরের সেবার ওপর নির্ভরশীল; request path-এ রাখলে ব্যবহারকারী অপেক্ষা করেন আর ইমেইল-সেবার ত্রুটি অর্ডারের ত্রুটি হয়ে যায়। Queue-তে কাজ রেখে উত্তর দিলে দুই পক্ষ আলাদা গতিতে চলে, ভিড় সমান হয় (load levelling) — ৪০/সেকেন্ড ক্ষমতায় ২০ সেকেন্ড ধরে ৮০/সেকেন্ড এলে প্রায় ৮০০টি জমে, পরে সরে। ক্ষতি যেখানে: ব্যবহারকারীর এখনই উত্তর লাগে (balance দেখা), ক্রম আর duplicate সামলানোর দায় আসে, আর debugging কঠিন হয়। Queue আসলে at-least-once দেয়, তাই consumer idempotent.
ফলো-আপ:
- “একটি বার্তা বারবার consumer-কে crash করাচ্ছে?” → poison message: backoff-সহ কয়েকবার চেষ্টা, তারপর dead letter queue — আর DLQ-তে alert, নইলে সেটি কবরস্থান।
- “Consumer বাড়াবেন কিসের ভিত্তিতে?” → CPU নয়; queue depth আর সবচেয়ে পুরোনো বার্তার বয়স।
প্র ৩২মাঝারি · RabbitMQ-ধাঁচের queue আর Kafka-ধাঁচের log — পার্থক্য কী, কখন কোনটি? (মাঝারি)
শক্তিশালী উত্তর: Queue-তে বার্তা ack হলে মুছে যায়; প্রতিটি বার্তা একজন কর্মী নেন — কাজ ভাগের জন্য আদর্শ, প্রতি বার্তায় আলাদা retry আর delay সহজ। Log-এ record মোছে না, প্রতিটির একটি offset; প্রতিটি consumer group নিজের offset রাখে — একই ঘটনা অনেক দল আলাদাভাবে পড়ে, আর পুরোনো offset থেকে আবার পড়া (replay) যায়। দাম: log-এ ক্রম শুধু partition-এর ভেতরে, আর একটি ধীর বা বিষাক্ত record পুরো partition আটকে দিতে পারে। তাই কাজ ভাগে queue, ঘটনার ধারা আর একাধিক পাঠকে log.
ফলো-আপ:
- “Pub/sub-এ ১০টি subscription থাকলে খরচ?” → গুণফল: সেকেন্ডে E event × N subscription = E·N delivery.
- “Retention কত?” → replay-র প্রয়োজন আর disk-এর দাম; key ধরে শেষ মান রাখতে log compaction.
প্র ৩৩মাঝারি · “আমাদের broker exactly-once delivery দেয়” — এই দাবিতে কী প্রশ্ন করবেন? (মাঝারি)
শক্তিশালী উত্তর: Network-এ timeout মানে “জানি না” — বার্তা হারাল, নাকি কাজ হয়ে ack হারাল, প্রেরক আলাদা করতে পারে না। তাই পাঠানোর স্তরে exactly-once সম্ভব নয়; সম্ভব effectively-once = at-least-once delivery + idempotent প্রক্রিয়াকরণ। শর্ত: কাজের ফল আর “এটি দেখা হয়েছে” চিহ্ন (inbox সারি বা offset) একই local transaction-এ। Kafka-ধাঁচের idempotent producer আর transaction broker-এর ভেতরে এটি দেয়; কিন্তু শিকলের বাইরের কড়া — database, ইমেইল, payment provider — নিজের idempotency key ছাড়া সুরক্ষিত নয়। তাই প্রশ্ন: “শেষ side effect পর্যন্ত কি?”
ফলো-আপ:
- “Dedup store কত বড়?” → হার × window × প্রতি entry-র byte; সেকেন্ডে ১০ হাজার, ২৪ ঘণ্টা, ৪০ byte ধরলে প্রায় ৩৪.৫৬ GB — তাই প্রায়ই per-producer sequence number.
- “Offset কখন commit?” → কাজের পরে; আগে করলে crash-এ বার্তা হারায়।
প্র ৩৪অভিজ্ঞ · প্রতিটি ব্যবহারকারীর ঘটনা ক্রমে প্রক্রিয়া করতে হবে, অথচ throughput-ও লাগবে। কীভাবে? (কঠিন)
শক্তিশালী উত্তর: সারা বিশ্বের এক ক্রম লাগে না — লাগে প্রতি key-তে ক্রম। User ID-কে partition key দিন: একই ব্যবহারকারীর সব record একই partition-এ, সেখানে ক্রম রক্ষা; আলাদা ব্যবহারকারী আলাদা partition-এ সমান্তরালে। সমান্তরালতার ছাদ partition-এর সংখ্যা: একটি group-এ partition-এর চেয়ে বেশি consumer অলস বসে থাকেন, তাই partition আগেই যথেষ্ট রাখুন। ঝুঁকি: একজন খুব সক্রিয় ব্যবহারকারী একটি partition-কে গরম করেন, আর একটি বিষাক্ত record সেই partition-এর পেছনের সবাইকে আটকায় — তাকে আলাদা retry পথে সরাতে হয়, তবে তখন সেই key-এর ক্রম ভাঙে কি না ভাবতে হয়।
ফলো-আপ:
- “Partition সংখ্যা পরে বাড়ালে?” → key থেকে partition-এর হিসাব বদলায়, একই key-এর পুরোনো আর নতুন record দুই partition-এ — বদলের মুহূর্তে ক্রম ভাঙতে পারে।
- “Consumer-এর ভেতরে thread pool দিলে?” → partition-এর ক্রম ভাঙে, যদি না key ধরে thread ভাগ করেন।
প্র ৩৫অভিজ্ঞ · Event sourcing আর CQRS কখন নেবেন — আর কখন একেবারেই নয়? (কঠিন)
শক্তিশালী উত্তর: Event sourcing শুধু বর্তমান অবস্থা নয়, প্রতিটি ঘটনা রাখে — মুদি দোকানের খাতার পুরো পাতার মতো, শুধু শেষ যোগফল নয়। লাভ: পূর্ণ audit, অতীতের যেকোনো মুহূর্তের অবস্থা, আর নতুন read model পরে বানানো। CQRS লেখা আর পড়ার মডেল আলাদা করে; read model একটু পিছিয়ে থাকে, তাই read-your-writes আলাদা করে সামলাতে হয়। দাম: event-এর schema চিরকাল বহন, replay-র সময় (snapshot লাগে), “মুছে ফেলার অধিকার”-এর কঠিন প্রশ্ন, আর দলের শেখার খরচ। টাকার খাতা বা নিয়ন্ত্রক-চাহিদার ডোমেইনে মানানসই; সাধারণ CRUD অংশে প্রায়ই over-engineering. দুটি আলাদা — একটি অন্যটি ছাড়াই সম্ভব।
ফলো-আপ:
- “একই stream-এ দুজন একসাথে লিখলে?” → expected version: “version ৪ দেখে লিখছি” — মাঝে কেউ লিখলে conflict, আবার পড়ে চেষ্টা।
প্র ৩৬মাঝারি · প্রতি মিনিটে কতবার অর্ডার হলো — stream-এ গুনছেন, কিন্তু মোবাইল offline থেকে দেরিতে ঘটনা পাঠায়। কোন সময় ধরে গুনবেন? (মাঝারি)
শক্তিশালী উত্তর: ঘটনা কখন ঘটেছে (event time), processor কখন দেখল তা নয় (processing time). Processing time ধরলে দেরিতে আসা ঘটনা ভুল মিনিটে পড়ে — পর্ব ৩৬-এর simulator-এ প্রতি মিনিটের সঠিক ৬-এর জায়গায় এল ৪, ৫, ৬, ৭, ২। কিন্তু event time-এ প্রশ্ন জাগে: window কখন বন্ধ? Watermark হলো processor-এর অনুমান — “এর চেয়ে পুরোনো ঘটনা আর আসবে না।” Trade-off: আগে বন্ধ করলে দ্রুত ফল, কিন্তু দেরির ঘটনা বাদ বা সংশোধন; দেরিতে বন্ধ করলে ঠিক ফল, কিন্তু দেরি আর বেশি state. দেরির ঘটনা allowed lateness পর্যন্ত ফল সংশোধন করে, তারপর আলাদা পথে।
ফলো-আপ:
- “Batch-এ এই সমস্যা নেই?” → কম, কারণ গতকালের সব ডেটা এসে গেছে বলে ধরা হয় — দাম পুরো একদিনের দেরি।
- “রাত ১২টায় ১০ হাজার tenant-এর রিপোর্ট job?” → এক সেকেন্ডে ১০ হাজার job-এর ঢল; tenant-এর hash দিয়ে এক ঘণ্টায় ছড়ালে সেকেন্ডে কয়েকটি মাত্র।
৭ · Distributed systems-এর তত্ত্ব — CAP, consistency, quorum, consensus, ঘড়ি, lock আর CRDT
রিভিশন: পর্ব ৩৮ · Partial failure, পর্ব ৩৯ · সময় আর ক্রম, পর্ব ৪০ · CAP আর consistency, পর্ব ৪১ · Quorum, পর্ব ৪২ · Raft, পর্ব ৪৩ · Lock আর fencing, পর্ব ৪৪ · Gossip, পর্ব ৪৫ · Bloom আর HLL, পর্ব ৪৬ · CRDT, আর পর্ব ৬১ · ক্যাপস্টোন KV store
প্র ৩৭শুরু · একটি call-এ timeout হলো। এ থেকে আপনি নিশ্চিতভাবে কী জানলেন? (সহজ)
শক্তিশালী উত্তর: প্রায় কিছুই না — timeout মানে “জানি না”। তিনটি ঘটনা বাইরে থেকে হুবহু এক: অনুরোধ পৌঁছায়নি, কাজ হয়ে উত্তর হারিয়েছে, বা node শুধু ধীর। এটাই partial failure: এক যন্ত্রে “সব বা কিছুই না”, অনেক যন্ত্রে “কিছু, আর অজানা”। তাই নকশার তিনটি অভ্যাস: retry নিরাপদ করতে idempotency, “মরেছে” সিদ্ধান্তকে একক node-এর হাতে না রেখে quorum বা consensus-এ, আর পুরোনো ধারককে fencing দিয়ে আটকানো। Timeout-এর মান নিজেই trade-off: ছোট হলে সুস্থ node-কে মৃত ভাবা, বড় হলে সত্যিকারের মৃত্যু ধরা পড়ে দেরিতে।
ফলো-আপ:
- “শত শত node-এ কে বেঁচে আছে জানবেন কীভাবে?” → সবাই সবাইকে heartbeat দিলে বার্তা n(n − ১); gossip বা SWIM-এ প্রতি সদস্যের ভার n-নিরপেক্ষ, খবর ছড়ায় প্রায় log n রাউন্ডে।
প্র ৩৮অভিজ্ঞ · Redis-এ TTL-সহ একটি lock নিয়ে শুধু একজন worker যেন স্টক কমায়। এতে কী ভুল হতে পারে? (কঠিন)
শক্তিশালী উত্তর: আগে প্রশ্ন: lock কীসের জন্য? Efficiency lock ব্যর্থ হলে বাড়তি কাজ মাত্র; correctness lock ব্যর্থ হলে টাকা বা স্টক ভুল। বিপদ থেমে থাকা ধারক: worker A lock পেল, তারপর GC বা VM-এর বিরতিতে থেমে রইল, lease ফুরাল, B lock পেয়ে লিখল, A জেগে উঠে না জেনেই লিখল — দুজন ধারক। Lock service একে থামাতে পারে না, কারণ A নিজেই জানে না সে থেমে ছিল। প্রতিকার fencing token: প্রতিবার lock-এর সাথে বাড়তে থাকা নম্বর (৩৩, ৩৪), আর storage ছোট নম্বরের লেখা প্রত্যাখ্যান করে। অনেক ক্ষেত্রে lock-ই লাগে না: শর্তসহ লেখা (CAS বা version), বা প্রতিটি key-এর একজন লেখক।
দুর্বল উত্তর দেখতে যেমন: “TTL বড় করে দেব।” — বিরতি যেকোনো দৈর্ঘ্যের হতে পারে।
ফলো-আপ:
- “Storage যদি token যাচাই করতে না পারে?” → তখন lock একা সঠিকতার নিশ্চয়তা দেয় না; শর্তসহ লেখা বা ভিন্ন নকশা লাগে।
- “একজন চালককে দুই যাত্রীর কাছে পাঠানো ঠেকাবেন কীভাবে?” → চালকের অবস্থা বদলান শুধু compare-and-set দিয়ে; পর্ব ৫৮-এর simulator-এ সাধারণ “আগে পড়া, তারপর লেখা”-তে ৩৬% ক্ষেত্রে double offer, CAS-এ শূন্য।
প্র ৩৯মাঝারি · CAP theorem নিজের ভাষায় বলুন। “আমাদের database CA” — এই দাবির সমস্যা কী? (মাঝারি)
শক্তিশালী উত্তর: Network ভাগ হলে একটি সিস্টেম একসাথে linearizable থাকতে আর প্রতিটি চালু node থেকে উত্তর দিতে পারে না — Brewer-এর অনুমান (২০০০), Gilbert আর Lynch-এর প্রমাণ (২০০২)। Partition বাছাইয়ের জিনিস নয়, network ভাঙবেই; বাছাই শুধু তখন C না A. তাই একাধিক যন্ত্রের সিস্টেমকে “CA” বলা অর্থহীন। আর CAP-এর A মানে “উঁচু uptime” নয় — majority-র দিক চালু রাখা CP সিস্টেমও প্রায় সবসময় সেবা দেয়। বেশিরভাগ দিনের প্রশ্ন PACELC-এ (Abadi, ২০১২): partition না থাকলেও শক্ত consistency মানে প্রতিটি কাজে অন্য replica-র সাথে round trip, অর্থাৎ latency.
ফলো-আপ:
- “ACID-এর C আর CAP-এর C কি এক?” → না; প্রথমটি অ্যাপের নিয়ম রক্ষা, দ্বিতীয়টি linearizability — পর্ব ২৪ আর ৪০।
- “একটি সিস্টেমে কি দুই বাছাই একসাথে?” → হ্যাঁ, feature ধরে: শেষ সিট আর টাকা কাটা linearizable; প্রোফাইল ছবি eventual, সাথে read-your-writes; like counter eventual আর CRDT.
- “Serializable আর linearizable কি এক?” → না; serializability একাধিক object-এর transaction যেন কোনো এক ক্রমে চলেছে — বাস্তব সময় মানতে বাধ্য নয়; linearizability একটি object-এর, বাস্তব সময় মেনে। দুটি একসাথে হলে strict serializability.
প্র ৪০মাঝারি · N = ৩ replica-য় W = ২, R = ২. কেন কাজ করে, কতগুলো বিকলতা সয়, আর তবু পুরোনো মান আসতে পারে কেন? (মাঝারি)
শক্তিশালী উত্তর: R + W > N হলে যেকোনো লেখার দল আর যেকোনো পড়ার দল অন্তত W + R − N = ১টি replica-তে মেলে — পড়া অন্তত একটি নতুন কপি ছোঁয় (quorum intersection). একটি replica বিকল হলেও পড়া আর লেখা দুটিই চলে। কিন্তু quorum মানেই linearizable নয়: চলমান লেখা কিছু replica-তে পৌঁছেছে, ব্যর্থ আংশিক লেখা থেকে গেছে, sloppy quorum অন্য node-এ লিখেছে, বা একসাথে দুটি লেখায় LWW একটি ফেলেছে — overlap থাকলেও পুরোনো বা হারানো মান আসতে পারে। নিচের ছোট script সব সম্ভাব্য দল গুনে overlap যাচাই করে।
ফলো-আপ:
- “লেখা দ্রুত চাই — W = ১?” → তখন R = N লাগবে overlap-এর জন্য, আর একটি replica বন্ধ হলেই পড়া আটকায়।
- “Replica-গুলো মিলবে কীভাবে?” → hinted handoff, read repair আর Merkle tree দিয়ে anti-entropy.
// Quorum check by brute force: for N replicas, list EVERY possible write set of size W and
// read set of size R, and find the smallest overlap. Also: how many replicas may be down
// while writes (N - W) and reads (N - R) still succeed.
function subsets(n, k, start = 0, cur = [], out = []) {
if (cur.length === k) { out.push(new Set(cur)); return out; }
for (let i = start; i < n; i++) subsets(n, k, i + 1, [...cur, i], out);
return out;
}
function minOverlap(N, W, R) {
let min = Infinity;
for (const w of subsets(N, W)) for (const r of subsets(N, R)) {
let common = 0; for (const x of r) if (w.has(x)) common++;
min = Math.min(min, common);
}
return min;
}
console.log(" N W R R+W>N? min overlap writes survive reads survive");
for (const [N, W, R] of [[3, 2, 2], [3, 3, 1], [3, 1, 1], [5, 3, 3], [5, 4, 2], [5, 2, 2]]) {
const ok = R + W > N ? "yes" : "no";
console.log(String(N).padStart(2) + String(W).padStart(3) + String(R).padStart(3) + ok.padStart(9) +
String(minOverlap(N, W, R)).padStart(14) + (`${N - W} down`).padStart(17) + (`${N - R} down`).padStart(16));
}আউটপুট:
N W R R+W>N? min overlap writes survive reads survive
3 2 2 yes 1 1 down 1 down
3 3 1 yes 1 0 down 2 down
3 1 1 no 0 2 down 2 down
5 3 3 yes 1 2 down 2 down
5 4 2 yes 1 1 down 3 down
5 2 2 no 0 3 down 3 down
R + W > N যেখানে “yes”, সেখানে প্রতিটি সম্ভাব্য জোড়ায় অন্তত ১টি replica মেলে; “no” হলে এমন জোড়া আছে যারা একটিও replica ভাগ করে না — তখন পড়া একটিও নতুন কপি না ছুঁয়ে পুরোনো মান দিতে পারে। শেষ দুই কলামে দাম: (৩, ৩, ১)-এ পড়া দ্রুত আর ২টি বিকলতা সয়, কিন্তু একটি replica বন্ধ হলেই লেখা থামে; (৫, ৩, ৩)-এ দুই দিকেই ২টি। তাই উত্তরটি হওয়া উচিত “কোন কাজ বেশি, আর কোনটির থামা বেশি ক্ষতির” — একটি সংখ্যা নয়।
প্র ৪১অভিজ্ঞ · Raft cluster-এ ৩টির বদলে ৪টি সার্ভার রাখলে কি বেশি নিরাপদ? (কঠিন)
শক্তিশালী উত্তর: না। Raft-এ প্রতিটি সিদ্ধান্তে majority লাগে: ২f + ১টি সার্ভার f-টি crash সয়। ৩-এ majority ২, সয় ১; ৪-এ majority ৩, সয় তবুও ১; ৫-এ majority ৩, সয় ২। জোড় সংখ্যায় লাভ নেই, বরং প্রতিটি commit-এ বেশি জনের অপেক্ষা। কেন majority: যেকোনো দুটি majority অন্তত একজনে মেলে, তাই নতুন leader পুরোনো commit-এর খবর পায়ই — ভোট পায় কেবল সেই candidate, যার log অন্তত ভোটদাতার মতো হালনাগাদ। দাম: প্রতিটি commit-এ majority-র সাথে একটি round trip — region পেরোলে দশ থেকে শত ms. তাই consensus রাখা হয় metadata, leader election আর config-এর মতো ছোট কিন্তু জরুরি ডেটায়।
ফলো-আপ:
- “Leader থেকে পড়লেই কি সর্বশেষ মান?” → না-ও হতে পারে; সে নিজে জানে না নতুন leader হয়ে গেছে কি না — read index বা lease লাগে।
- “Paxos-এর সাথে সম্পর্ক?” → একই সমস্যার পুরোনো সমাধান; Raft (২০১৪) বোঝার সুবিধার জন্য নকশা করা।
প্র ৪২মাঝারি · দুই region-এ একই প্রোফাইল বদলাল; timestamp দেখে পরেরটি রাখি (last-write-wins). এতে সমস্যা কী? (মাঝারি)
শক্তিশালী উত্তর: আলাদা যন্ত্রের ঘড়ি আলাদা চলে — ২০ ppm সরলে দিনে প্রায় ১.৭ সেকেন্ড — আর NTP-র পরে লাফায়। ঘড়ির পার্থক্যের চেয়ে কাছাকাছি দুটি লেখায় “পরের” লেখাটি ছোট timestamp পেতে পারে, আর LWW তা নিঃশব্দে ফেলে দেয় — কোনো error নেই। Lamport clock কারণ-কার্যের ক্রম রাখে, কিন্তু দুটি ঘটনা একসাথে (concurrent) কি না বলতে পারে না; vector clock পারে — তখন দুটি সংস্করণই (sibling) রেখে মেলানো যায়। কখন LWW চলে: মান পুরোপুরি বদলে দেওয়া হয় আর মাঝে মাঝে একটি হারানো সহনীয়, যেমন “শেষ দেখা সময়”।
ফলো-আপ:
- “সময়কাল মাপতে কোন ঘড়ি?” → monotonic clock; wall clock পেছাতে পারে।
- “সবচেয়ে সস্তা প্রতিকার?” → conflict এড়ানো — প্রতিটি ব্যবহারকারীর লেখা তাঁর “বাড়ির” region-এ।
প্র ৪৩অভিজ্ঞ · Offline-এ চলা একটি অ্যাপে CRDT কখন ঠিক উত্তর, আর কখন CRDT দিয়েও হবে না? (কঠিন)
শক্তিশালী উত্তর: CRDT-র merge commutative, associative আর idempotent — যেকোনো ক্রমে, যতবার খুশি মেলালেও একই ফল, coordination ছাড়াই (strong eventual consistency). Counter (G-Counter, PN-Counter), set (OR-Set — add-wins), আর collaborative লেখায় চমৎকার। দাম: metadata আর tombstone জমে, আর merge-এর অর্থ সবসময় ব্যবসার অর্থ নয়। যা পারে না: “ব্যালান্স শূন্যের নিচে নয়” বা “সিট একজনেরই” — এমন নিয়ম দুই পক্ষের আলাদা সিদ্ধান্তে ভাঙতে পারে; দুই offline ফোন একই শেষ টাকা খরচ করলে merge তা ফেরাতে পারে না। সেখানে coordination লাগবেই, বা আগে থেকে ভাগ করা কোটা।
ফলো-আপ:
- “Shopping cart-এ union-এ মেলালে কী হয়?” → মুছে ফেলা জিনিস ফিরে আসে — Dynamo-র cart-এর পরিচিত উদাহরণ; OR-Set তা সামলায়।
প্র ৪৪মাঝারি · ১০ কোটি username-এর “নেই” প্রশ্ন দ্রুত দিতে Bloom filter দেবেন। কত memory, আর ভুল কোন দিকে? (মাঝারি)
শক্তিশালী উত্তর: Bloom filter বলে “নিশ্চিত নেই” বা “হয়তো আছে”; ভুল শুধু এক দিকে — false positive. ১% ভুলে প্রতি key-এ প্রায় ৯.৬ bit আর ৭টি hash: ১০ কোটি × ৯.৫৮৫ bit ≈ ১২০ MB; ০.১%-এ প্রায় ১৪.৪ bit আর ১০টি hash. Trade-off কে দাম দেয় তাতে: “হয়তো আছে” এলে database-এ নিশ্চিত হতে হয় — সামান্য বাড়তি কাজ, তাই এখানে মানানসই। কিন্তু চূড়ান্ত সিদ্ধান্তে নয় — “নামটি নেওয়া হয়েছে” বলে কাউকে ফিরিয়ে দেওয়া ভুল হবে। সাধারণ Bloom থেকে মোছা যায় না; লাগলে counting বা cuckoo filter.
ফলো-আপ:
- “আলাদা দর্শক কতজন, প্রায় কম memory-তে?” → HyperLogLog: ১৬,৩৮৪টি register, প্রায় ১২ KB, ভুল প্রায় ০.৮১%; দুই sketch ঘর ধরে max নিলে মিলিত গণনা।
- “সবচেয়ে জনপ্রিয় URL?” → count-min sketch আর একটি ছোট heap — কখনো কম দেখায় না, বাড়তি দেখাতে পারে।
৮ · Reliability আর operations — resilience, rate limiting, SLO, DR, deployment আর নিরাপত্তা
রিভিশন: পর্ব ৪৭ · Microservices, পর্ব ৪৮ · Resilience, পর্ব ৪৯ · Rate limiting, পর্ব ৫০ · Observability, পর্ব ৫১ · Disaster recovery, পর্ব ৫২ · নিরাপত্তা, পর্ব ৫৩ · Deployment
প্র ৪৫শুরু · নতুন একটি পণ্য শুরু করছেন। Monolith না microservices? (সহজ)
শক্তিশালী উত্তর: সাধারণত modular monolith: একটি deployable, ভেতরে পরিষ্কার module-সীমানা। Microservices দেয় দলের স্বাধীনতা, আলাদা deploy আর আলাদা scaling — বিনিময়ে network call, ছড়ানো ডেটা, distributed transaction, বেশি operations আর কঠিন debugging. লাভটি মূলত সংগঠনের: অনেক দল একই কোডে একে অপরকে আটকালে। ছোট দলে সেই সমস্যা নেই, দাম আছে। পরে ভাঙতে হলে strangler fig — একটি একটি feature কেটে আলাদা করা।
দুর্বল উত্তর দেখতে যেমন: “Microservices আধুনিক আর scalable, তাই শুরু থেকেই।”
ফলো-আপ:
- “Distributed monolith চিনবেন কীভাবে?” → কয়েকটি সেবা একই টেবিলে লেখে, একটি অনুরোধে অনেক call, আর সবাইকে একসাথে deploy করতে হয়।
- “সেবার সীমানা কীসে?” → ব্যবসার ভাষায় — bounded context আর ডেটার মালিকানা; টেবিল বা কোডের স্তর ধরে নয়।
প্র ৪৬মাঝারি · Dependency ব্যর্থ হলে retry করবেন — কতবার, কতক্ষণ পরপর, আর কোন স্তরে? (মাঝারি)
শক্তিশালী উত্তর: শুধু ক্ষণিকের ত্রুটিতে (timeout, 503) আর শুধু idempotent কাজে; ভুল ইনপুটে নয়। মাঝে exponential backoff আর full jitter — jitter না থাকলে সব client একই মুহূর্তে ফেরে; পর্ব ৪৮-এর simulator-এ ১০০টি client-এর ভিড় সরতে jitter ছাড়া ৪৬২ সেকেন্ড, full jitter-এ ৮.৮. স্তরে স্তরে retry গুণ হয়: তিন স্তরের প্রত্যেকে ৩ বার চেষ্টা করলে সবচেয়ে নিচের সেবা দেখে ৩ × ৩ × ৩ = ২৭টি — ঠিক যখন সে আগেই কষ্টে। তাই retry একটি স্তরে, আর একটি retry budget — যেমন মোট অনুরোধের বড়জোর ১০% retry.
ফলো-আপ:
- “Retry-র মোট সময়ের সীমা?” → পুরো অনুরোধের deadline, যা নিচের সব call-এ পৌঁছায়; deadline পেরোলে retry অর্থহীন।
প্র ৪৭মাঝারি · Timeout, circuit breaker আর bulkhead — তিনটির কাজ আলাদা কোথায়? (মাঝারি)
শক্তিশালী উত্তর: ধীর dependency মৃতের চেয়েও খারাপ: মৃত সেবা ১ ms-এ “না” বলে, ধীর সেবা প্রতিটি thread কয়েক সেকেন্ড আটকে রাখে, আর Little-এর সূত্রে thread ফুরিয়ে সুস্থ কাজও থামে — cascading failure. Timeout একটি call-এর অপেক্ষা সীমিত করে; ঊর্ধ্বসীমাও হিসাব করা যায় — ২০০ thread-এর pool আর সেকেন্ডে ১০০ call হলে গড় অপেক্ষা ২ সেকেন্ড ছাড়ালেই pool ভরে। Circuit breaker বারবার ব্যর্থ dependency-কে কিছুক্ষণ ডাকাই বন্ধ করে (closed → open → half-open), দ্রুত “না” দেয়। Bulkhead প্রতিটি dependency-কে আলাদা pool দেয় — একটি ধীর হলেও বাকিরা চলে। তিনটি একসাথে লাগে, আর সাথে একটি fallback.
ফলো-আপ:
- “Health check-এ database-ও দেখবেন?” → সাবধানে; database ধীর হলে সব instance একসাথে “অসুস্থ” হয়ে বাদ পড়তে পারে — liveness অগভীর রাখা।
প্র ৪৮মাঝারি · “মিনিটে ১০০ অনুরোধ” সীমা দেবেন। Fixed window, sliding window না token bucket? (মাঝারি)
শক্তিশালী উত্তর: Fixed window সবচেয়ে সস্তা — একটি counter — কিন্তু ঘড়ির সীমানায় ২ সেকেন্ডে ২০০টি ছাড়ে। Sliding window counter দুটি সংখ্যায় কাছাকাছি অনুমান দেয়। Token bucket দুটি knob দেয়: গড় হার r আর একসাথে সর্বোচ্চ b; যেকোনো T সেকেন্ডে বড়জোর b + r·T — burst ইচ্ছা করে অনুমোদিত, কিন্তু সীমিত। বাছাই নির্ভর করে burst কতটা সহনীয় তাতে। Distributed হলে “পড়ে তারপর লেখা” counter-এ সীমা ফুটো হয়; atomic INCR বা script লাগে। আর কার হিসাব: user, API key বা tenant — IP শুধু মোটা দাগে, কারণ CGNAT-এর পেছনে বহু মানুষ একই ঠিকানায়। নিচের script সীমানার burst মেপে দেখায়।
ফলো-আপ:
- “সীমা পেরোলে কী উত্তর?” → 429 আর Retry-After; client-এ backoff আর jitter.
- “Rate limit আর load shedding কি এক?” → না; rate limit নীতি — সার্ভার অলস থাকলেও; shedding ভিড়ে সবাইকে বাঁচানোর জরুরি ব্যবস্থা।
// Limit "100 requests per minute". A client sends 1 request every 10 ms from t = 59 s to t = 61 s:
// 200 attempts in 2 seconds, right across the minute boundary at 60 s. How many does each
// limiter admit, second by second? Times are integer milliseconds, so the output is exact.
const LIMIT = 100, WIN = 60000;
function fixedWindow() {
const count = new Map();
return t => { const w = Math.floor(t / WIN), c = count.get(w) || 0;
if (c < LIMIT) { count.set(w, c + 1); return true; } return false; };
}
function slidingCounter() { // estimate = prev window * overlap share + current window
const count = new Map();
return t => { const w = Math.floor(t / WIN), share = 1 - (t % WIN) / WIN;
const est = (count.get(w - 1) || 0) * share + (count.get(w) || 0);
if (est < LIMIT) { count.set(w, (count.get(w) || 0) + 1); return true; } return false; };
}
function tokenBucket(rate, burst) { // rate tokens per ms, bucket starts full
let tokens = burst, last = 0;
return t => { tokens = Math.min(burst, tokens + (t - last) * rate); last = t;
if (tokens >= 1) { tokens -= 1; return true; } return false; };
}
const limiters = { "fixed window": fixedWindow(), "sliding counter": slidingCounter(),
"token bucket": tokenBucket(LIMIT / WIN, LIMIT) };
console.log("limiter 59-60 s 60-61 s total in 2 s");
for (const [name, allow] of Object.entries(limiters)) {
let a = 0, b = 0;
for (let t = 59000; t < 61000; t += 10) if (allow(t)) { if (t < 60000) a++; else b++; }
console.log(name.padEnd(16) + String(a).padStart(8) + String(b).padStart(10) + String(a + b).padStart(15));
}আউটপুট:
limiter 59-60 s 60-61 s total in 2 s
fixed window 100 100 200
sliding counter 100 2 102
token bucket 100 3 103
একই ২ সেকেন্ডের ঝাঁক, তিন ফল। Fixed window ৫৯–৬০ সেকেন্ডে পুরোনো মিনিটের ১০০টি দেয়, ৬০ সেকেন্ডে counter শূন্য হতেই আরও ১০০ — ২ সেকেন্ডে ২০০, ঘোষিত হারের দ্বিগুণ। Sliding counter আগের মিনিটের ১০০-কে প্রায় পুরো ওজনে গোনে, তাই নতুন মিনিটের শুরুতে মাত্র ২টি। Token bucket ভরা bucket-এর ১০০টি দেয়, তারপর হার অনুযায়ী (১০০ ÷ ৬০ ≈ ১.৬৭/সেকেন্ড) আর ৩টি — সূত্র b + r·T = ১০০ + ১.৬৭ × ২ ≈ ১০৩-এর সাথে মেলে। প্রশ্ন তাই “কোনটি সঠিক” নয়: শুরুর এই ১০০-র burst আপনার backend সইতে পারে কি না।
প্র ৪৯অভিজ্ঞ · ৩০ দিনে ৯৯.৯% SLO. Error budget কত, আর alert দেবেন কিসের ভিত্তিতে? (কঠিন)
শক্তিশালী উত্তর: Error budget = ১ − SLO = ০.১%: সময়ে ৩০ × ২৪ × ৬০ × ০.০০১ = ৪৩.২ মিনিট, বা সেকেন্ডে ১,০০০ অনুরোধে ২৫,৯২,০০০টি ব্যর্থ অনুরোধ। Alert ব্যর্থতার হারে নয়, budget খরচের গতিতে — burn rate. Burn rate ১৪.৪ মানে এক ঘণ্টায় মাসের budget-এর ১৪.৪ ÷ ৭২০ = ২% শেষ, সেই গতিতে পুরো budget ৫০ ঘণ্টায়। একটি প্রচলিত ধাঁচ: ১ ঘণ্টা আর ৫ মিনিট — দুই জানালাতেই ১৪.৪ পেরোলে page; লম্বা জানালা ভুল alarm কমায়, ছোটটি সমস্যা থামলে alert দ্রুত বন্ধ করে। Budget শেষ হলে নীতি: নতুন feature-এর বদলে নির্ভরযোগ্যতার কাজ।
দুর্বল উত্তর দেখতে যেমন: “CPU ৮০% ছাড়ালে page দেব।” — কারণ ধরে alert; ব্যবহারকারী কষ্ট পাচ্ছেন কি না বলে না।
ফলো-আপ:
- “SLI কী মাপবেন?” → ব্যবহারকারীর চোখে: সফল অনুরোধের অনুপাত, আর লক্ষ্যের চেয়ে দ্রুত অনুরোধের অনুপাত — load balancer বা client-এর কাছ থেকে।
- “১০০% SLO কেন নয়?” → অসম্ভব আর অসীম দামি; budget-ই deploy আর পরীক্ষার জায়গা দেয়।
প্র ৫০মাঝারি · “তিনটি replica আছে, তাই আলাদা backup লাগবে না।” কী বলবেন? (মাঝারি)
শক্তিশালী উত্তর: Replica যন্ত্র বা zone হারানো থেকে বাঁচায়, কিন্তু ভুল DELETE, নীরবে নষ্ট ডেটা বা ransomware সেকেন্ডেই সব replica-তে পৌঁছায় — তখন লাগে অতীতে ফেরার backup. দুটি সংখ্যা ব্যবসা ঠিক করে: RPO — কত সময়ের ডেটা হারানো চলে; RTO — কতক্ষণ বন্ধ থাকা চলে। Point-in-time recovery (snapshot + WAL) RPO কমায়; warm standby বা active-active RTO কমায় — খরচ বাড়িয়ে। নিয়ম: 3-2-1, আলাদা account-এ বদলানো যায় না এমন কপি, আর নিয়মিত restore-মহড়া — যে backup কখনো restore করে দেখেননি, তা backup নয়; মহড়াতেই আসল RTO মাপা যায়।
ফলো-আপ:
- “Failover-এর ধাপ?” → টের পাওয়া, সিদ্ধান্ত, পুরোনো primary-কে fencing, promote, traffic সরানো (DNS-এর TTL মাথায় রেখে), পরে ধীরে failback.
প্র ৫১অভিজ্ঞ · একটি কলামের নাম বদলাতে হবে, downtime ছাড়া। Rolling, blue-green না canary — আর database-এর ধাপগুলো কী? (কঠিন)
শক্তিশালী উত্তর: কোডের জন্য: rolling-এ বাড়তি যন্ত্র কম লাগে কিন্তু দুই সংস্করণ একসাথে চলে; blue-green-এ মুহূর্তে switch আর ফেরা, দ্বিগুণ capacity-র দামে; canary অল্প traffic দিয়ে মেপে এগোয় — পর্ব ৫৩-এর simulation-এ ১৫ মিনিটে ধরা পড়া bug-এ ক্ষতি big-bang-এর মাত্র ২.৭%. কিন্তু কলামের নাম এক ধাপে বদলালে যেকোনো কৌশলেই পুরোনো কোড ভাঙে। তাই expand → contract: নতুন কলাম যোগ → দুই জায়গায় লেখা → পুরোনো ডেটা backfill → পড়া নতুন কলামে → পুরোনো লেখা বন্ধ → শেষে পুরোনো কলাম মোছা। প্রতিটি ধাপ আগের কোডের সাথে মানানসই, তাই যেকোনো ধাপে rollback চলে।
ফলো-আপ:
- “Canary ৪০০ অনুরোধে error দ্বিগুণ — rollback?” → ছোট নমুনায় পার্থক্য প্রায়ই প্রমাণিত নয় (পর্ব ৫৩-এ z = 1.73); ২,০০০ অনুরোধে পরিষ্কার (z = 5.44) — “সব ঠিক” প্রায়ই আসলে “এখনো জানি না”।
- “Deploy আর release আলাদা কেন?” → feature flag দিয়ে কোড আগে পৌঁছায়, ফিচার পরে খোলে — বন্ধের সুইচ এক ক্লিকে।
প্র ৫২মাঝারি · API gateway token যাচাই করছে। তাহলে ভেতরের order সেবার কি নিজে কিছু যাচাই করতে হবে? (মাঝারি)
শক্তিশালী উত্তর: হ্যাঁ। Gateway বলে “আপনি কে” (authentication); “এই অর্ডারটি কি এঁর?” (authorization) প্রতিটি অনুরোধে সেবাকেই দেখতে হয় — role থাকলেই হবে না। এর অভাব (BOLA) API-র সবচেয়ে পরিচিত ঝুঁকি: শুধু URL-এর ID বদলে অন্যের ডেটা দেখা। আরও প্রতিরক্ষা: ভেতরেও mTLS আর least privilege (zero trust); token-এ স্বাক্ষর, algorithm, iss, aud, exp — সব যাচাই; ব্রাউজার আর মোবাইলে OAuth 2.0-র authorization code flow + PKCE; সংরক্ষণে envelope encryption — প্রতিটি ফাইলের নিজের DEK, তাকে মোড়ে KMS-এর KEK; secret vault-এ, কোডে নয়।
ফলো-আপ:
- “Password কীভাবে রাখবেন?” → ধীর, salt দেওয়া hash — Argon2id, bcrypt বা scrypt; সাথে MFA বা passkey.
- “OAuth আর OIDC-র পার্থক্য?” → OAuth অনুমতি দেয় (access token API-র জন্য), OIDC পরিচয় জানায় (ID token client-এর জন্য)।
৯ · ভালো ইন্টারভিউয়ের আচরণ — প্রশ্ন পরিষ্কার করা, আপত্তি সামলানো, না জানা স্বীকার, আর red flag
রিভিশন: পর্ব ৬ · নকশার কাঠামো (ইন্টারভিউর ৪৫ মিনিট), পর্ব ২ · Requirement; পূর্ণ নকশায় অনুশীলন পর্ব ৬৬-এ
কারিগরি জ্ঞান সমান হলেও দুইজনের ইন্টারভিউ আলাদা শোনায় — একজন প্রশ্ন বুঝে নেন, অনুমান বলেন, আপত্তিকে তথ্য হিসেবে নেন; আরেকজন তাড়াহুড়ো করেন বা তর্কে জড়ান। এই অংশের তিনটি প্রশ্ন সেই আচরণ নিয়ে।
প্র ৫৩শুরু · ইন্টারভিউয়ার শুধু বললেন, “এখানে একটি cache যোগ করবেন?” প্রথম ৩০ সেকেন্ডে কী বলবেন? (সহজ)
শক্তিশালী উত্তর: দুই-তিনটি ধারালো প্রশ্ন, তারপর একটি স্পষ্ট অনুমান আর সিদ্ধান্ত: “পড়া আর লেখার অনুপাত কেমন? ডেটা কতক্ষণ পুরোনো থাকলে ক্ষতি নেই? — যদি পড়া অনেক বেশি আর কয়েক সেকেন্ডের staleness চলে, তাহলে হ্যাঁ: cache-aside, ছোট TTL আর লেখার পরে delete. ভুল হলে জানাবেন।” তারপর জোরে ভাবতে ভাবতে এগোনো। দশটি প্রশ্নের তালিকা নয় — সেই প্রশ্নগুলোই, যার উত্তরে সিদ্ধান্ত বদলায়। উত্তর না পেলে নিজেই যুক্তিসংগত অনুমান ধরে নিন আর মুখে বলুন।
দুর্বল উত্তর দেখতে যেমন: দুই মিনিট চুপ করে ভেবে হঠাৎ “Redis দেব” — বা উল্টোটা, প্রশ্নের পর প্রশ্ন, কোনো সিদ্ধান্ত নয়।
ফলো-আপ:
- “আমি কোনো তথ্য দেব না, আপনি ঠিক করুন।” → “তাহলে ধরে নিচ্ছি পড়া:লেখা ১০০:১ আর ৩০ সেকেন্ডের staleness চলে” — অনুমান লিখে রেখে এগোনো, পরে বদলানো সহজ।
প্র ৫৪মাঝারি · আপনি queue প্রস্তাব করলেন; ইন্টারভিউয়ার বললেন, “আমার মনে হয় এখানে queue লাগবে না।” কীভাবে সাড়া দেবেন? (মাঝারি)
শক্তিশালী উত্তর: আপত্তিকে নতুন তথ্য হিসেবে নিন, আক্রমণ হিসেবে নয়। আগে কারণ জিজ্ঞেস করুন: “কোন দিকটা ভাবছেন — latency, না জটিলতা?” তারপর trade-off খোলাখুলি আবার মাপুন। কারণ যুক্তিসংগত হলে মেনে নিন আর বলুন কী বদলাল: “ঠিক, ব্যবহারকারী এখনই ফল চান — তাহলে sync call, timeout আর retry.” আপনার পক্ষে সংখ্যা থাকলে বিনয়ের সাথে ধরে রাখুন: “তবে peak-এ সেকেন্ডে ৮০টি আসে আর ক্ষমতা ৪০টি — queue ছাড়া ভিড়ের ২০ সেকেন্ডে প্রায় ৮০০টি অনুরোধ ব্যর্থ হবে; বিকল্প হলে consumer বাড়ানো।” অনেক সময় আপত্তিটি পরীক্ষাই — আপনি যুক্তিতে দাঁড়ান, না প্রথম চাপেই সরে যান।
দুর্বল উত্তর দেখতে যেমন: সাথে সাথে “ঠিক আছে, বাদ দিলাম” — কোনো কারণ ছাড়াই; বা “না, queue-ই লাগবে” বলে তর্ক।
প্র ৫৫অভিজ্ঞ · এমন একটি প্রশ্ন এল যার উত্তর আপনি সত্যিই জানেন না — যেমন “Spanner-এর TrueTime ঠিক কীভাবে commit-এর ক্রম নিশ্চিত করে?” কী করবেন? (কঠিন)
শক্তিশালী উত্তর: সৎভাবে সীমানা টানুন, তারপর যতটুকু জানেন সেখান থেকে যুক্তি দিন: “বিস্তারিত নিশ্চিত নই। যতটুকু জানি — Google-এর প্রকাশিত Spanner গবেষণাপত্র (২০১২) অনুযায়ী ঘড়ি একটি সময় নয়, অনিশ্চয়তার একটি সীমা দেয়; commit-এর পরে সেই অনিশ্চয়তা পেরোনো পর্যন্ত অপেক্ষা (commit-wait) করে, যাতে পরের transaction বড় timestamp পায়। এখান থেকে অনুমান করছি — অনিশ্চয়তা যত ছোট, অপেক্ষা তত কম।” কোনটি জানা আর কোনটি অনুমান, আলাদা করে বলুন, আর বলুন কীভাবে যাচাই করতেন। বানানো খুঁটিনাটি বিশ্বাস ভাঙে; সৎ “জানি না, তবে এভাবে ভাবছি” বিশ্বাস বাড়ায়।
দুর্বল উত্তর দেখতে যেমন: আত্মবিশ্বাসের সাথে বানানো সংখ্যা আর নাম — একটি follow-up-এই ধরা পড়ে।
ফলো-আপ:
- “তাহলে ঘড়ি ছাড়া এই সমস্যা কীভাবে সমাধান করতেন?” → logical clock, বা প্রতিটি commit-এ consensus-এর ক্রম — বাস্তব সময়ের সাথে মেলানোর দামসহ (প্র ৪২)।
Red flag — যে বাক্যগুলো শুনলে অগভীর বোঝাপড়া ধরা পড়ে
নিচের বাক্যগুলো নিজে থেকে “ভুল” নয় — কোনো প্রসঙ্গে সত্যও হতে পারে। Red flag হয় তখন, যখন এগুলো প্রশ্ন, সংখ্যা আর দাম ছাড়া বলা হয়।
| Red flag বাক্য | কেন অগভীর শোনায় | বদলে যা বলবেন |
|---|---|---|
| “এখানে Kafka ব্যবহার করব।” (প্রশ্নের শুরুতেই) | টুল আগে, প্রয়োজন পরে | “কাজটি async হতে পারে কি না, ক্রম আর replay লাগে কি না — দেখে queue না log.” |
| “NoSQL বেশি scalable.” | Access pattern আর নিশ্চয়তার প্রশ্ন বাদ | “প্রধান query আর লেখার চাপ এই; তাই key-value-তে এটা পাই, join হারাই।” |
| “আমরা CA সিস্টেম বানাব।” | Partition বাছাইয়ের জিনিস নয় | “Partition হলে এই feature-এ consistency, ওটায় availability.” |
| “Cache দিলেই দ্রুত হবে।” | Staleness, stampede আর ঠান্ডা cache উপেক্ষিত | “Hit ratio কত আশা করি, কতটা পুরোনো চলে, cache খালি হলে database টিকবে কি না।” |
| “Retry দিলেই নির্ভরযোগ্য।” | Duplicate আর retry storm | “Idempotent কাজে, backoff আর jitter-সহ, একটি স্তরে, budget-এ বাঁধা।” |
| “Broker exactly-once দেয়, তাই duplicate নেই।” | শিকলের শেষ side effect ভুলে যাওয়া | “At-least-once আর idempotent consumer — effect আর dedup-চিহ্ন এক transaction-এ।” |
| “গড় latency ৫০ ms, তাই ঠিক আছে।” | লেজ লুকানো | “p99 আর p99.9 কত, fan-out-এ লেজ কতটা বাড়ে।” |
| “শুরু থেকেই microservices.” | দাম না দেখে ফ্যাশন | “Modular monolith থেকে শুরু; দল আর deploy-এর চাপ এলে সীমানা ধরে ভাঙা।” |
| “Replica আছে, backup লাগবে না।” | ভুল DELETE আর নষ্ট ডেটাও replicate হয় | “RPO আর RTO কত; point-in-time backup আর restore-মহড়া।” |
| “Distributed lock নিলেই একজনই লিখবে।” | থেমে থাকা ধারক | “Lease-এর সাথে fencing token, বা lock ছাড়াই শর্তসহ লেখা।” |
| “Timestamp দেখে নতুনটা রাখব।” | ঘড়ির পার্থক্যে লেখা নিঃশব্দে হারায় | “Version বা vector clock, বা প্রতিটি key-এর একজন লেখক।” |
| “৯৯.৯৯৯% availability দেব।” | সংখ্যার দাম না জানা | “বছরে প্রায় ৫ মিনিট — কোন অংশে সত্যিই লাগে, আর এর খরচ কত।” |
| “বড় প্রতিষ্ঠান এভাবেই করে।” | যাচাই-অযোগ্য দাবি, প্রসঙ্গ আলাদা | “প্রকাশিত গবেষণাপত্রে এই নকশা আছে; আমাদের requirement-এ মেলে কারণ …” |
প্রতিটি “সবসময়” আর “কখনো না” একটি follow-up ডাকে। শক্তিশালী উত্তর প্রায় সবসময় শর্তসাপেক্ষ: “যদি পড়া বেশি আর staleness চলে, তাহলে…”। শর্তটি মুখে বললে ইন্টারভিউয়ার দেখেন আপনি দামটা চেনেন — আর শর্ত বদলালে সিদ্ধান্তও বদলাতে প্রস্তুত।
১০ · AI-এর যুগে — AI দিয়ে ধারণার প্রশ্নের অনুশীলন, যাচাইসহ
AI একটি ধৈর্যশীল mock interviewer হতে পারে — অবিরাম follow-up দেয়, আপনার উত্তরে ফাঁক খোঁজে। কিন্তু system design-এর প্রশ্নে এর ভুলগুলো চেনা, আর ভুলগুলো আত্মবিশ্বাসের সাথে বলা হয়:
| AI-এর সাধারণ ভুল | কীভাবে ধরবেন |
|---|---|
| প্রতিটি প্রশ্নে একই ছাঁচ — “Kafka, Redis আর microservices যোগ করুন” | জিজ্ঞেস করুন: কোন সংখ্যা বা requirement এই বাক্সটি দাবি করে? উত্তর না থাকলে বাক্সটি বাদ |
| হিসাবে একটি ×১,০০০ বা ×৮ হারানো; ৮৬,৪০০ আর ১০৫ মিশিয়ে ফেলা | প্রতিটি ধাপ এককসহ নিজে আবার গুনুন, বা ছোট script-এ চালান |
| ACID-এর C আর CAP-এর C, বা serializable আর linearizable গুলিয়ে ফেলা | পর্ব ২৪ আর ৪০-এর সংজ্ঞার সাথে প্রতিটি দাবি মিলিয়ে দেখুন |
| “Quorum থাকলে সবসময় সর্বশেষ মান”, “exactly-once delivery সম্ভব” — শর্ত বাদ দেওয়া | “কোন ব্যর্থতায় এটি ভাঙে?” — এই follow-up AI-কেই করুন, তারপর নিজে যাচাই |
| কোনো পণ্যের সীমা, দাম বা default বানিয়ে বলা | অফিসিয়াল documentation; সংস্করণভেদে বদলায় |
| “অমুক প্রতিষ্ঠানে এই প্রশ্ন আসে” — বানানো তালিকা আর প্রক্রিয়ার বর্ণনা | এ ধরনের দাবি উপেক্ষা করুন; ধারণা আর পদ্ধতি অনুশীলন করুন |
AI-কে mock interviewer বানাতে চাইলে নিয়মগুলো স্পষ্ট দিন — একবারে একটি প্রশ্ন, আপনার উত্তরের পরেই মূল্যায়ন আর follow-up:
AI-এর দেওয়া উত্তর মুখস্থ করার আগে — চেকলিস্ট
নিজেকে যাচাই করুন
ইন্টারভিউর ধাঁচের ধারণা আর মুখে মুখে হিসাব। ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।
ক্রমএকটি ধারণাভিত্তিক প্রশ্নের শক্তিশালী উত্তরের ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)
- ❓ প্রশ্ন পরিষ্কার করা — পড়া-লেখার অনুপাত, কতটা পুরোনো ডেটা চলে
- 📖 এক বাক্যে সংজ্ঞা
- ⚖️ Trade-off — কী পাই, কী দিই
- 🔢 কখন কোন দিক জেতে — একটি সংখ্যা বা উদাহরণসহ
- 🧪 কী ভাঙতে পারে, আর কীভাবে মেপে যাচাই করব
(সহজ) একটি অনুরোধ ১০০টি স্বাধীন সার্ভারের সবার উত্তরের অপেক্ষা করে। প্রতিটি সার্ভার আলাদাভাবে ১% সময় ধীর। মোটামুটি কত শতাংশ অনুরোধ অন্তত একটি ধীর উত্তরে আটকাবে?
- প্রায় ১%
- প্রায় ১০%
- প্রায় ৬৩%
- ১০০%
(মাঝারি) একটি সার্ভারে একটি অনুরোধের নিজস্ব সেবা-সময় ১০ ms. সরল M/M/1 মডেলে (গড় সময় = S ÷ (১ − ρ)) utilization ০.৫ থেকে ০.৯ হলে গড় সময় কত থেকে কত হয়?
- ২০ ms থেকে ১০০ ms
- ২০ ms থেকে ২২ ms
- ১৫ ms থেকে ১৯ ms
- দুটিতেই ১০ ms
(সহজ) একটি অনুরোধ পরপর তিনটি সার্ভিসের সবাইকে চায়; প্রত্যেকটির availability ৯৯.৯%, ব্যর্থতাগুলো স্বাধীন। পুরো অনুরোধের availability মোটামুটি কত?
- ৯৯.৯%
- প্রায় ৯৯.৭%
- প্রায় ৯৯.৯৭%
- প্রায় ৯৭%
(সহজ) HTTP-র সংজ্ঞা অনুযায়ী কোন method idempotent নয়, তাই টাকা কাটার মতো কাজে আলাদা Idempotency-Key লাগে?
- GET
- PUT
- DELETE
- POST
(মাঝারি) Cache-এর key সার্ভারে ভাগ হয় hash(key) mod N দিয়ে। সার্ভার ৪ থেকে ৫টি করলে মোটামুটি কত ভাগ key-এর সার্ভার বদলাবে?
- প্রায় ২০%
- প্রায় ২৫%
- প্রায় ৮০%
- ১০০%
(মাঝারি) একটি জনপ্রিয় key-এ সেকেন্ডে ২,০০০টি অনুরোধ আসে। মেয়াদ ফুরালে database থেকে মান আবার হিসাব করতে ৫০ ms লাগে, আর কোনো lock বা soft TTL নেই। মেয়াদ শেষের মুহূর্তে মোটামুটি কতগুলো একই query database-এ যাবে?
- ১টি
- প্রায় ১০০টি
- প্রায় ২,০০০টি
- প্রায় ৪০টি
(কঠিন) Wallet-এর balance ১,০০০ টাকা। দুটি অনুরোধ একসাথে balance পড়ে, app-এ বিয়োগ করে ৮০০ আর ৬০০ তুলে নতুন মান লেখে; database READ COMMITTED-এ। কোনটি এই lost update সবচেয়ে সরলভাবে ঠেকায়?
- শর্তসহ atomic UPDATE — balance যথেষ্ট থাকলে তবেই বিয়োগ
- কিছুই লাগবে না, READ COMMITTED এমনিই ঠেকায়
- Balance cache-এ রেখে সেখান থেকে পড়া
- balance কলামে একটি index যোগ করা
(মাঝারি) একটি leaderless store-এ প্রতিটি key-এর N = ৫টি replica, লেখা সফল হয় W = ৩টি ack-এ। প্রতিটি পড়া যেন অন্তত একটি সর্বশেষ সফল লেখার replica ছোঁয়, সেজন্য সবচেয়ে ছোট R কত?
- ১
- ২
- ৫
- ৩
(সহজ) ৫টি সার্ভারের একটি Raft cluster-এ একসাথে সর্বোচ্চ কতগুলো সার্ভার crash করলেও cluster নতুন লেখা commit করতে পারে?
- ১টি
- ২টি
- ৩টি
- ৪টি
(মাঝারি) একটি CP (consistency-অগ্রাধিকার) store-এ network দুই ভাগ হলো: এক দিকে ৩টি node, অন্য দিকে ২টি। ২টির দিকে একজন client লিখতে চাইলেন। সাধারণত কী ঘটবে?
- লেখা সফল হবে, পরে দুই দিক মিলিয়ে নেওয়া হবে
- লেখাটি নিঃশব্দে অন্য মান দিয়ে বদলে যাবে
- লেখাটি ব্যর্থ হবে বা আটকে থাকবে, কারণ এই দিক সংখ্যালঘু
- পুরো store, দুই দিকই, বন্ধ হয়ে যাবে
(মাঝারি) Storage সর্বশেষ যে fencing token দেখেছে তা ৩৪. এখন token ৩৩ নিয়ে একটি লেখা এল — পুরোনো একজন lock-ধারক দীর্ঘ বিরতির পর জেগে উঠেছেন। Storage-এর কী করা উচিত?
- লেখাটি প্রত্যাখ্যান করা
- লেখাটি গ্রহণ করা, কারণ ধারকের কাছে বৈধ token আছে
- দুই লেখার গড় নেওয়া
- Lock service-কে জিজ্ঞেস করে অপেক্ষা করা
(মাঝারি) একটি Bloom filter-এ false-positive হার ১% চাই, hash-এর সংখ্যা সেরা মানে। প্রতি key-এ মোটামুটি কত bit লাগবে?
- প্রায় ১ bit
- প্রায় ৪.৮ bit
- প্রায় ৬৪ bit
- প্রায় ৯.৬ bit
(মাঝারি) একটি token bucket-এ হার সেকেন্ডে ১০টি token, ধারণক্ষমতা ৫০, শুরুতে পূর্ণ। একজন client টানা যত দ্রুত সম্ভব অনুরোধ পাঠালে প্রথম ৫ সেকেন্ডে সর্বোচ্চ কতটি ছাড়া পাবে?
- ৫০টি
- ৬০টি
- ১০০টি
- ২৫০টি
(কঠিন) ৩০ দিনের SLO ৯৯.৯%. টানা ১ ঘণ্টা burn rate ১৪.৪ থাকলে ৩০ দিনের error budget-এর কত অংশ খরচ হয়?
- ০.১%
- ২%
- ১৪.৪%
- ৫০%
(মাঝারি) একটি consumer queue থেকে “wallet-এ টাকা যোগ” বার্তা পড়ে। Broker at-least-once দেয়। কোন নকশায় প্রতিটি যোগ ঠিক একবার কার্যকর হবে (effectively-once)?
- কাজ শুরুর আগেই ack পাঠানো
- Consumer-এ retry পুরো বন্ধ রাখা
- Consumer-এর memory-তে দেখা বার্তার id রাখা
- বার্তার id দিয়ে inbox সারি আর টাকা যোগ — একই database transaction-এ
(সহজ) একটি log topic-এ ৮টি partition. একই consumer group-এ ১২টি consumer চালু করা হলো। কতজন consumer কোনো partition পাবেন না?
- ৪ জন
- কেউ না — সবাই কিছু না কিছু পাবেন
- ৮ জন
- ১২ জন
শব্দকোষ
লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব শব্দ এখানে একসাথে:
মনে রাখুন
- ধারণার প্রশ্নের উত্তর একটি trade-off: সংজ্ঞা, কী পাই, কী দিই, কখন কোন দিক জেতে, আর একটি সংখ্যা।
- প্রথমে দুটি প্রশ্ন প্রায় সবখানে খাটে: পড়া না লেখা বেশি, আর কতটা পুরোনো ডেটা চলে।
- মুখে রাখার সংখ্যা: ১ − (১ − p)N, S ÷ (১ − ρ), series-এ গুণ, mod N-এ N/(N + ১), R + W > N, ২f + ১, b + r·T, burn rate ÷ ৭২০.
- প্রতিটি “সবসময়”-এর পেছনে একটি ব্যর্থতার ঘটনা খুঁজুন: stale set, থেমে থাকা lock-ধারক, quorum-এর ফাঁক, retry-র গুণফল, ঠান্ডা cache.
- আপত্তিকে তথ্য হিসেবে নিন, না জানলে সীমানা টেনে যুক্তি দিন, আর red flag বাক্যের বদলে শর্তসাপেক্ষ, মাপা উত্তর দিন।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পর্ব ৬৬ · Mock interview — পূর্ণ walkthroughপরবর্তী পর্বweb crawler, leaderboard, pastebin আর আরও নকশা, শুরু থেকে শেষ।
- পর্ব ৬৪ · লিখিত ও মৌখিক প্রশ্নপাশের অনুশীলনপরীক্ষার ধাঁচের সংজ্ঞা, তুলনা আর ব্যাখ্যা।
- সিস্টেম ডিজাইন · কোর্স হোম৬৬টি পর্বপুরো কোর্সের রোডম্যাপ — কোন পর্ব কখন।
- DBMS ও SQL · database design ইন্টারভিউগভীরে যানSchema, index আর transaction-এর ইন্টারভিউ প্রশ্ন।
- Computer Networks · নেটওয়ার্কিং ইন্টারভিউপাশের ট্র্যাকTCP, TLS, DNS আর load balancer-এর গভীর প্রশ্ন।
- Operating Systems · OS ইন্টারভিউপাশের ট্র্যাকProcess, thread, lock আর memory — সার্ভারের ভেতরের ভিত্তি।