🚀 Giới thiệu
Hiệu năng là yếu tố sống còn của mọi ứng dụng backend. Một API chậm không chỉ làm giảm trải nghiệm người dùng mà còn tốn tài nguyên hệ thống.
NestJS cung cấp sẵn công cụ mạnh mẽ là CacheModule và Interceptor, giúp bạn tăng tốc API dễ dàng mà không cần thay đổi logic kinh doanh.
Trong bài viết này, bạn sẽ học cách:
- Cấu hình Redis cache trong NestJS.
- Tạo Cache Interceptor tùy chỉnh.
- Sử dụng cache hiệu quả với TTL.
- Làm sạch cache khi dữ liệu thay đổi.
🧩 Cache là gì và khi nào nên dùng?
Cache là cơ chế lưu trữ tạm thời dữ liệu để truy cập nhanh hơn trong lần gọi tiếp theo.
Khi một API phải truy vấn cơ sở dữ liệu hoặc dịch vụ ngoài nhiều lần, việc cache kết quả giúp giảm tải đáng kể.
📈 Khi nào nên dùng cache
- API đọc nhiều – ghi ít (ví dụ: danh sách sản phẩm, thống kê).
- Dữ liệu ít thay đổi trong thời gian ngắn.
- Truy vấn tốn tài nguyên (nhiều phép join hoặc tính toán phức tạp).
🧱 Cấu hình Cache trong NestJS
1️⃣ Cài đặt Redis
npm install cache-manager ioredis cache-manager-ioredis-yet
2️⃣ Đăng ký CacheModule
// app.module.ts
import { CacheModule, Module } from '@nestjs/common';
import { redisStore } from 'cache-manager-ioredis-yet';
@Module({
imports: [
CacheModule.registerAsync({
useFactory: async () => ({
store: await redisStore({
host: 'localhost',
port: 6379,
ttl: 10, // thời gian cache mặc định 10 giây
}),
}),
isGlobal: true,
}),
],
})
export class AppModule {}
⚡ Nếu bạn chưa có Redis, xem hướng dẫn Redis Quick Start.
🧠 Sử dụng Cache Interceptor
NestJS có sẵn CacheInterceptor
, bạn có thể áp dụng trực tiếp ở mức global hoặc cho từng route.
Áp dụng toàn cục
// main.ts
import { CacheInterceptor } from '@nestjs/cache-manager';
import { APP_INTERCEPTOR } from '@nestjs/core';
app.useGlobalInterceptors(new CacheInterceptor(app.get(CacheModule)));
Áp dụng cho controller
@UseInterceptors(CacheInterceptor)
@Controller('products')
export class ProductController {
@Get()
findAll() {
return this.productService.findAll();
}
}
Lần đầu request sẽ truy vấn DB, nhưng lần sau sẽ lấy từ cache → tốc độ nhanh hơn đáng kể.
🧩 Tạo Cache Interceptor tùy chỉnh
Đôi khi bạn muốn tùy biến key cache hoặc TTL riêng cho từng API.
@Injectable()
export class CustomCacheInterceptor extends CacheInterceptor {
trackBy(context: ExecutionContext): string | undefined {
const request = context.switchToHttp().getRequest();
return `custom_cache:${request.url}`;
}
protected override async intercept(context: ExecutionContext, next: CallHandler): Promise<Observable<any>> {
const response$ = await super.intercept(context, next);
console.log('✅ Cached response triggered');
return response$;
}
}
Áp dụng:
@UseInterceptors(CustomCacheInterceptor)
@Get(':id')
async getProduct(@Param('id') id: string) {
return this.productService.findOne(id);
}
🔁 Làm sạch cache khi dữ liệu thay đổi
Cache cần được làm mới khi dữ liệu thay đổi.
Ví dụ, khi bạn thêm hoặc xóa sản phẩm, cache cũ không còn đúng nữa.
async createProduct(data: CreateProductDto) {
const product = await this.repo.save(data);
await this.cacheManager.reset(); // Xóa cache toàn bộ
return product;
}
Hoặc bạn có thể chỉ xóa cache theo key:
await this.cacheManager.del('custom_cache:/products');
✅ Ưu điểm khi dùng Cache và Interceptor
Lợi ích | Mô tả |
---|---|
Tăng tốc API | Giảm thời gian phản hồi đáng kể. |
Giảm tải database | Hạn chế truy vấn trùng lặp. |
Tách biệt logic | Không cần thay đổi code service. |
Dễ mở rộng | Có thể áp dụng cho từng module cụ thể. |
⚠️ Lỗi thường gặp
Lỗi phổ biến | Giải pháp |
---|---|
Redis không kết nối được | Kiểm tra cổng 6379 hoặc config trong CacheModule . |
Dữ liệu cũ không bị xóa | Dùng TTL ngắn hoặc reset cache thủ công khi ghi dữ liệu. |
Cache không hoạt động | Đảm bảo CacheInterceptor được đăng ký chính xác. |
Key cache bị trùng | Sử dụng trackBy() để tạo key riêng. |
🔗 Tham khảo thêm
💬 Kết luận
Cache và Interceptor là cặp công cụ tuyệt vời giúp bạn xây dựng API hiệu năng cao mà vẫn giữ cấu trúc sạch.
Hơn nữa, chúng cho phép tách biệt logic nghiệp vụ và tối ưu hệ thống một cách an toàn.
Vì vậy, nếu bạn muốn ứng dụng NestJS của mình phản hồi nhanh hơn gấp nhiều lần — hãy bắt đầu triển khai cache ngay hôm nay!