Chapters of Frontend Dev থেকে Full-Stack Backend

Week 3 - Interview-এ সবচেয়ে বেশি জিজ্ঞেস করা TopicsChapter 15 of 282 min read

Englishবাংলা

Caching - Redis, cache-aside pattern আর invalidation-এর কঠিন প্রশ্ন

Cache কেন দরকার, cache-aside pattern, TTL, invalidation কখন করবেন, stale data-র risk

আপনার menu page-টা প্রতিদিন হাজার বার দেখা হয়, কিন্তু menu বদলায় সপ্তাহে একবার। তবু প্রতিটা view-তেই database-এ একই query ছুটছে, একই data আসছে। এটা অনেকটা এরকম - একই ঠিকানা বারবার খাতা খুলে খোঁজা, অথচ ঠিকানাটা ফোনে সেভ করলেই হতো। Cache হলো সেই সেভ করা ব্যবস্থা: ঘন ঘন লাগা data দ্রুত জায়গা (Redis - memory-তে থাকে) রেখে দেওয়া, যাতে database-এর কাছে প্রতিবার যেতে না হয়।

Cache-aside pattern - সবচেয়ে বেশি ব্যবহৃত ছক

async function getMenu() {
  const cached = await redis.get("menu:all");
  if (cached) return JSON.parse(cached);   // cache hit

  const menu = await db.menu.findMany();   // cache miss - database থেকে
  await redis.set("menu:all", JSON.stringify(menu), "EX", 300); // ৫ মিনিট TTL
  return menu;
}

ছকটা সরল: প্রথমে cache-এ খুঁজুন, পেলে সঙ্গে সঙ্গে ফেরত দিন। না পেলে database থেকে এনে cache-এ রেখে দিন, যাতে পরের জন পেয়ে যায়। EX 300 হলো TTL - ৫ মিনিট পর cache নিজে থেকেই মুছে যাবে, পরের request-এ টাটকা data আসবে।

Invalidation - cache-এর আসল কঠিন সমস্যা

Cache-এর সবচেয়ে জটিল প্রশ্নটা হলো: data বদলে গেলে পুরনো cache কখন সরাবেন? Admin menu-তে দাম বদলালেন, কিন্তু cache-এ পুরনো দাম রয়ে গেল - customer ভুল দাম দেখবে। দুটো অস্ত্র আছে: TTL (নিজে থেকে expire হওয়া - মাঝে মাঝে পুরনো data দেখা মেনে নেওয়া যায় এমন জায়গায়), আর সক্রিয় invalidation - data বদলালেই সংশ্লিষ্ট cache key মুছে দেওয়া।

// দাম বদলালেই menu cache ফেলে দিন
async function updateMenuItem(id, data) {
  const item = await db.menu.update({ where: { id }, data });
  await redis.del("menu:all");
  return item;
}

কী cache করবেন সেটাও বিচার: যা ঘন ঘন পড়া হয় কিন্তু কম বদলায় (menu, settings, জনপ্রিয় product) - সেগুলো। যা প্রতিবারই আলাদা বা সবসময় নির্ভুল থাকতেই হবে (bank balance, stock-এর শেষ অবস্থা) - সেখানে সাবধান, কিংবা cache-ই করবেন না।

সবাই যে ভুলটা করে

Cache করে TTL বা invalidation-এর ব্যবস্থা না রাখা - তাহলে পুরনো data অনন্তকাল ধরে ঘুরতে থাকে। উল্টোটাও ভুল: সবকিছু cache করা। Cache যত বাড়ে, stale data-র ঝুঁকি তত বাড়ে। যেখানে সুবিধা পরিষ্কার, শুধু সেখানেই cache।

আজকের Practice

আপনার API-তে Redis বসিয়ে menu বা product list endpoint-এ cache-aside pattern যোগ করুন। তারপর দুইবার request পাঠিয়ে সময় মাপুন - প্রথমবার database থেকে, দ্বিতীয়বার cache থেকে। শেষে একটা আইটেম আপডেট করে দেখুন invalidation কাজ করছে কিনা।

Interview-এ কীভাবে বলবেন

আমি cache-aside pattern ব্যবহার করি - আগে Redis-এ খুঁজি, না পেলে database থেকে এনে TTL দিয়ে রেখে দিই। Invalidation-এর জন্য যেখানে data বদলানো সঙ্গে সঙ্গে দেখাতেই হবে, সেখানে update-এর সময় key মুছে দিই; যেখানে সামান্য পুরনো data চলবে, সেখানে শুধু TTL-ই যথেষ্ট।

All chapters of Frontend Dev থেকে Full-Stack Backend