পাঠ্যক্রম খুলুন
প্রাথমিক পর্যায়

Cache Invalidation: পুরোনো data সরানো ও expiry

Cache Invalidation and Expiration

এই পাঠের কুইজ ↓৬ মিনিট পড়াPHP 8.3+ · Laravel 12
এই পাঠের সূচিপত্র

এই পাঠে যা শিখবেন

  • TTL, explicit eviction ও versioned keys
  • Commit ও refill race
  • Representation অনুযায়ী invalidation scope

সমস্যা দিয়ে শুরু

Admin একটি বইয়ের দাম বদলালেন। Product page update হলো, কিন্তু category list পুরোনো দাম রাখল। এক row-এর data বহু cached representation-এ থাকতে পারে। Invalidation-এর কঠিন অংশ key delete করা নয়; কোন পরিবর্তনে কোন representation পুরোনো হয় এবং concurrent reader কী করবে তা বোঝা।

সহজ করে বুঝি

TTL value কতক্ষণ fresh ধরে reuse করা যাবে তার সময়সীমা। Explicit invalidation write-এর পরে সংশ্লিষ্ট key সরায়। Versioned key-তে schema বা data generation identity বদলে নতুন namespace নেওয়া হয়। TTL correctness-এর universal guarantee নয়: miss loader পুরোনো snapshot থেকে fill করলে নতুন TTL-সহ stale value আসতে পারে। Key-তে tenant, locale, currency ও representation version প্রাসঙ্গিক হলে রাখতে হবে। TTL expiry eviction policy থেকে আলাদা; memory pressure-এ value আগে উধাও হতে পারে।

পরিচিত একটি উপমা

দোকানের printed price list-এর মেয়াদ আছে, কিন্তু দুপুরে দাম বদলালে পুরোনো কপি তুলে নেওয়া দরকার। নতুন সংস্করণের তালিকা আলাদা নম্বর পেলে কোনটি latest বোঝা সহজ। তবে কেউ পুরোনো draft আবার photocopy করলে শুধু মেয়াদ লিখে সমস্যার শেষ হয় না।

নকশাটি দেখুন

Diagram লোড হচ্ছে…

Reader প্রথমে পুরোনো database state পেয়েছে।
Diagram-এর text flow দেখুন
sequenceDiagram
 participant R as Reader
 participant D as Database
 participant W as Writer
 participant C as Redis
 R->>D: Read old product
 W->>D: Commit new product
 W->>C: Delete key
 R->>C: Fill old product with new TTL

Reader প্রথমে পুরোনো database state পেয়েছে। Writer commit করে key delete করে। Reader পরে পুরোনো result cache-এ রাখায় stale value আবার জন্মায়। তাই “commit-এর পরে delete করেছি” সব race বন্ধ করে না। Short TTL ক্ষতির সময় কমাতে পারে; stronger solution-এ version check, coordinated loader বা monotonic generation দরকার হতে পারে।

PHP ও Laravel-এ প্রয়োগ

নিচের action fragment two affected keys invalidation দেখায়। Product category ID পুরোনো ও নতুন দুই ক্ষেত্রেই আলাদা হলে দুটো category key মুছতে হবে; এখানে category বদলায়নি ধরে নেওয়া হয়েছে। Authorized validated update এবং configured Redis store দরকার।

php
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;

$product = DB::transaction(function () use ($product, $data) {
    $product->update($data);
    return $product;
});

$cache = Cache::store('redis');
$cache->forget("product:v2:{$product->id}");
$cache->forget("category:v1:{$product->category_id}:page:1");

সুবিধা, সীমাবদ্ধতা ও trade-off

Short TTL implementation সহজ এবং missed invalidation-এর lifetime কমায়, তবে cache hit কমে। Broad namespace version bump অনেক key logically invalidate করে; পুরোনো keys memory নিতে থাকে TTL না ফুরানো পর্যন্ত। Targeted eviction সাশ্রয়ী কিন্তু dependency tracking জটিল। Redis flush সব application-এর unrelated data মুছতে পারে; shared infrastructure-এ এমন broad operation বিশেষ সতর্কতার বিষয়।

সাধারণ ভুল

  • Commit-এর আগে delete করে পুরোনো database থেকে refill হতে দেওয়া।
  • Product বদলালেও list/search representation ভুলে যাওয়া।
  • Cache tags সব Laravel driver-এ একইভাবে supported ভাবা।

আরও একটু গভীরে

Tenant cache namespace-এ authorization context রাখলেও permission change-এর invalidation দরকার হতে পারে। Read-your-writes চাইলে writer response সরাসরি committed value দিতে পারে, কিন্তু পরের read path-এর policy আলাদা। Versioned keys-এর version কোথা থেকে পড়বেন সেটিও consistency সমস্যা; প্রতিবার database পড়লে caching লাভ কমতে পারে। CDN cache, app cache ও browser cache আলাদা layer, একটির purge অন্যটিকে সরায় না।

মনে রাখুন

Invalidation data dependency ও concurrency-এর সমস্যা। TTL একটি সীমিত fallback, transaction নয়। Key identity এবং layer-specific policy লিখে রাখুন।

নিজে চেষ্টা করুন

একটি product rename-এর জন্য detail, category list ও search cache dependency map আঁকুন। উপরের stale refill timeline-এ TTL এক মিনিট হলে user কতক্ষণ পুরোনো data দেখতে পারেন তা assumptions-সহ লিখুন।

নিজের বোঝা যাচাই করুন

1. TTL কি exact freshness guarantee?

না। Loader কোন snapshot থেকে value এনেছে এবং পরে refill করেছে কি না তা গুরুত্বপূর্ণ। TTL cache insertion-এর সময় থেকে গণনা হতে পারে।

2. Delete সব race আটকায়?

না। Delete-এর আগে শুরু হওয়া reader পরে stale value fill করতে পারে। Timeline দিয়ে race পরীক্ষা করুন।

3. Versioned key কেন?

Representation schema বা generation বদলালে পুরোনো value নতুন reader ব্যবহার করে না। তবে পুরোনো key cleanup ও version distribution লাগবে।

4. সব key flush করব?

সাধারণ update-এ তা ব্যয়বহুল এবং shared data মুছতে পারে। Scope নির্দিষ্ট invalidation বা namespace design ব্যবহার করুন।

5. CDN purge করলে Redis মুছবে?

না। আলাদা cache layer-এর নিজস্ব storage ও policy থাকে। End-to-end freshness-এর জন্য সব relevant layer বিচার করুন।

আরও পড়ুন

এই পাঠের কুইজ

এই পাঠ থেকে ২টি প্রশ্ন। উত্তর দিয়ে ব্যাখ্যা দেখুন; অধ্যায়ের কুইজ আলাদাভাবে দিতে হবে।

এই পাঠের ২টি প্রশ্নের উত্তর দিন। পাস করতে দুটিই সঠিক হতে হবে।

জমা দেওয়ার পর সঠিক উত্তর ও ব্যাখ্যা দেখবেন। ফলাফল এই ব্রাউজারে সংরক্ষিত থাকবে। অনুশীলনের ফল অধ্যায় সম্পন্নের হিসাবে যোগ হয় না।

সব বিষয় মিলিয়ে অনুশীলন করুন →

অগ্রগতি এই ব্রাউজারে সংরক্ষিত থাকে। শুধু পাঠ খুললে সম্পন্ন হয় না।