🚀 CQRS (Command Query Responsibility Segregation) là gì?
CQRS (Command Query Responsibility Segregation) là mô hình kiến trúc giúp tách biệt phần đọc dữ liệu (Query) và ghi dữ liệu (Command).
💡 Tại sao cần CQRS?
Thông thường, trong kiến trúc truyền thống (Monolithic), chúng ta có một service xử lý cả đọc và ghi. Điều này có thể gây tắc nghẽn hiệu suất, đặc biệt khi hệ thống có số lượng đọc nhiều hơn số lượng ghi. CQRS giúp tách rời hai luồng này, tối ưu hiệu suất và giúp hệ thống dễ mở rộng hơn.
🔹 Cách hoạt động của CQRS
CQRS chia hệ thống thành hai phần chính:
1️⃣ Command (Ghi dữ liệu)
📌 Chỉ thay đổi trạng thái hệ thống, không trả về dữ liệu.
- Xử lý việc thêm, sửa, xóa dữ liệu.
- Có thể sử dụng Event Sourcing để lưu lịch sử thay đổi.
- Ví dụ:
CreateUserCommand
,UpdateOrderCommand
.
👉 Ví dụ Command trong NestJS
export class CreateUserCommand {
constructor(public readonly name: string, public readonly email: string) {}
}
👉 Command Handler
import { CommandHandler, ICommandHandler } from '@nestjs/cqrs';
@CommandHandler(CreateUserCommand)
export class CreateUserHandler implements ICommandHandler<CreateUserCommand> {
async execute(command: CreateUserCommand) {
console.log(`Creating user: ${command.name}, ${command.email}`);
return { id: Date.now(), ...command };
}
}
2️⃣ Query (Đọc dữ liệu)
📌 Chỉ đọc dữ liệu, không thay đổi trạng thái.
- Tối ưu hóa riêng cho truy vấn đọc.
- Có thể sử dụng cơ sở dữ liệu riêng cho đọc (Read Database).
- Ví dụ:
GetUserByIdQuery
,GetOrdersQuery
.
👉 Ví dụ Query trong NestJS
export class GetUsersQuery {}
👉 Query Handler
import { QueryHandler, IQueryHandler } from '@nestjs/cqrs';
@QueryHandler(GetUsersQuery)
export class GetUsersHandler implements IQueryHandler<GetUsersQuery> {
async execute(query: GetUsersQuery) {
console.log('Fetching users...');
return [{ id: 1, name: 'John Doe', email: 'john@example.com' }];
}
}
🔥 Lợi ích của CQRS
✅ Hiệu suất cao hơn → Tối ưu riêng cho đọc và ghi.
✅ Dễ mở rộng (Scalability) → Có thể dùng database khác nhau cho đọc/ghi.
✅ Tăng tính bảo mật → Hạn chế truy cập không hợp lệ vào dữ liệu ghi.
✅ Hỗ trợ Event Sourcing → Dễ dàng theo dõi và rollback thay đổi.
💡 Khi nào nên dùng CQRS?
- Khi hệ thống có số lượng đọc lớn hơn số lượng ghi.
- Khi cần tách biệt business logic để dễ bảo trì.
- Khi cần hỗ trợ event-driven architecture.
❌ Khi nào không nên dùng?
- Nếu hệ thống nhỏ, không có nhiều yêu cầu về hiệu suất.
- Khi chưa cần tối ưu hóa đọc/ghi riêng biệt.