পাঠ্যক্রম খুলুন
মধ্যবর্তী পর্যায়

CQRS: লেখা ও পড়ার model আলাদা রাখা

CQRS: Separate Read and Write Models

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

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

  • Read এবং write model আলাদা করুন
  • Projection lag দৃশ্যমান রাখুন
  • CQRS কখন অপ্রয়োজনীয় বুঝুন

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

Order write schema normalized, কিন্তু dashboard-এ customer, payment, delivery ও product join করে ধীর query চলছে। Team write table-এ অনেক reporting column যোগ করছে, transaction জটিল হচ্ছে। Reads এবং writes একই shape চায় না।

সহজ করে বুঝি

CQRS অর্থ Command Query Responsibility Segregation। Command state পরিবর্তনের business rule সামলায়; query পড়ার উপযোগী representation ফেরায়। আলাদা database বাধ্যতামূলক নয়। Read model event বা change থেকে projection হতে পারে। CQRS আর event sourcing ভিন্ন: বর্তমান-state database দিয়েও CQRS করা যায়।

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

স্কুলের ভর্তি register সঠিক official record রাখে, notice board শ্রেণিভিত্তিক সহজ তালিকা দেখায়। Notice board থেকে ভর্তি অনুমোদন করলে ভুল হবে; এটি পড়ার সুবিধার copy। Register বদলানোর পরে board update কিছুটা দেরি করতে পারে।

নকশাটি দেখুন

Diagram লোড হচ্ছে…

Read এবং write model আলাদা করুন
Diagram-এর text flow দেখুন
flowchart LR
 C[Command API] --> W[(Order Write Model)]
 W --> E[Committed Events]
 E --> P[Projection Worker]
 P --> R[(Dashboard Read Model)]
 Q[Query API] --> R

Command authoritative rules ও transaction চালায়। Committed event projection worker-এ যায়। Worker dashboard row বানায়, query সেই row পড়ে। Write success আর dashboard visibility এক মুহূর্তে নাও হতে পারে। Confirmation response-এ new order-এর identity দিলে user progress বুঝতে পারেন।

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

Laravel query controller fragment; tenant-scoped order_summaries projection আছে। Write controller আলাদা service-এ authoritative orders table ব্যবহার করবে। Projection index tenant_id,created_at এবং paginated read ধরে নিন। UI updated_at দিয়ে freshness জানাতে পারে।

php
use Illuminate\Support\Facades\DB;

$tenantId = $request->user()->tenant_id;
$rows = DB::table('order_summaries')
    ->where('tenant_id', $tenantId)
    ->orderByDesc('created_at')
    ->orderByDesc('order_id')
    ->cursorPaginate(25, [
        'order_id', 'customer_name', 'status',
        'total_minor', 'created_at', 'projected_at',
    ]);

return response()->json($rows);
// Authorization is still required even though this is only a read model.
// Never use stale summary values to authorize a financial write.

এটি PHP 8.3+ ও Laravel 12-এর শিক্ষামূলক fragment; সম্পূর্ণ application নয়। সংশ্লিষ্ট route-এ authentication ও resource authorization প্রয়োগ করতে হবে। নিচের অনুশীলনে failure ইচ্ছা করে তৈরি করুন; শুধু সফল response দেখে correctness ধরে নেবেন না।

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

Read schema optimize করা ও query scale আলাদা করা সহজ হয়। Projection replay, lag এবং schema migration operational খরচ বাড়ায়। সাধারণ CRUD app-এ ভালো indexes ও query optimization দিয়েই সমাধান হলে CQRS split বাড়তি complexity।

সাধারণ ভুল

  • CQRS মানেই দুই database ও microservices মনে করা।
  • Read model দেখে stock reservation অনুমোদন করা।
  • Projection failure হলে user-এর successful order হারিয়েছে বলা।

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

Projection rebuild-এর সময় নতুন version side-by-side বানিয়ে তারপর query switch করা যায়। Checkpoint ও projection update atomic না হলে duplicate বা skip হতে পারে। Idempotent upsert এবং event version ordering দরকার।

Projection worker থামিয়ে order create করুন। Command response success থাকবে, dashboard lag করবে। UI-তে pending visibility বা latest order direct link দিন। Worker ফিরে projection converge করা চাই। Rebuild চলাকালে পুরোনো read model চালু রাখার plan লিখুন।

মনে রাখুন

  • Write correctness ও read convenience আলাদা।
  • CQRS event sourcing নয়।
  • Projection freshness একটি contract।

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

E-commerce dashboard-এর denormalized row design করুন। কোন field authoritative নয় এবং কত lag গ্রহণযোগ্য উল্লেখ করুন।

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

1. দুই database চাই?

না। একই database-এ আলাদা command ও query model দিয়েও শুরু করা যায়।

2. Event sourcing আবশ্যক?

না। Current-state write model থেকে events দিয়ে projection বানানো সম্ভব।

3. Projection stale হলে?

UI-তে freshness জানাতে হবে; critical write authoritative model থেকে যাচাই করবে।

4. Rebuild কীভাবে?

Durable source থেকে নতুন model তৈরি, checkpoint যাচাই এবং controlled switch; replay source না থাকলে অন্য backfill দরকার।

5. কখন বাদ দেব?

সাধারণ CRUD ও indexed query যথেষ্ট হলে অতিরিক্ত projection pipeline-এর খরচ যুক্তিযুক্ত নয়।

আরও পড়ুন

এই পাঠের কুইজ

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

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

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

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

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