Nestjs项目实战 使用Redis进行缓存加速
在Nestjs项目中使用Redis进行缓存加速时遇到了几个问题想请教:
- 有没有推荐的在Nestjs中集成Redis的最佳实践方案?官方文档的@nestjs/cache-manager感觉不够详细
- 缓存数据时如何设置合理的TTL?不同类型的业务数据(如用户信息、商品列表)应该分别设置多久?
- 遇到缓存穿透问题时有什么好的解决方案?布隆过滤器在Nestjs中具体怎么实现?
- 项目需要先查Redis再查数据库,现在的代码耦合度较高,有没有优雅的装饰器或拦截器实现方案?
- 本地开发时用Docker跑Redis服务,但部署到线上环境后性能反而下降了,可能是什么原因?
3 回复
在NestJS中使用Redis进行缓存加速,首先需要安装@nestjs/redis
和ioredis
包:
npm install @nestjs/redis ioredis --save
然后在app.module.ts
中配置Redis模块:
import { Module } from '@nestjs/common';
import { APP_INTERCEPTOR } from '@nestjs/core';
import { RedisModule } from '@nestjs/redis';
import { ConfigService } from '@nestjs/config';
@Module({
imports: [
RedisModule.registerAsync({
useFactory: (configService: ConfigService) => ({
url: configService.get<string>('REDIS_URL'),
}),
inject: [ConfigService],
}),
],
providers: [
{
provide: APP_INTERCEPTOR,
useClass: CacheInterceptor, // 可以自定义拦截器
},
],
})
export class AppModule {}
接着创建一个缓存拦截器cache.interceptor.ts
来处理缓存逻辑:
import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { RedisService } from './redis.service';
@Injectable()
export class CacheInterceptor implements NestInterceptor {
constructor(private redisService: RedisService) {}
async intercept(context: ExecutionContext, next: CallHandler): Promise<Observable<any>> {
const key = this.generateCacheKey(context);
const cachedData = await this.redisService.get(key);
if (cachedData) {
return Observable.of(JSON.parse(cachedData));
}
return next.handle().pipe(
map(data => {
this.redisService.set(key, JSON.stringify(data));
return data;
}),
);
}
private generateCacheKey(context: ExecutionContext): string {
const req = context.switchToHttp().getRequest();
return `cache:${req.method}:${req.url}`;
}
}
最后在服务或控制器中使用这个拦截器即可实现缓存功能。记得在生产环境中设置合理的过期时间。
在NestJS项目中使用Redis进行缓存加速非常实用。首先,安装@nestjs/redis
和ioredis
:
npm install @nestjs/redis ioredis --save
然后,在app.module.ts
中配置Redis模块:
import { Module } from '@nestjs/common';
import { APP_INTERCEPTOR } from '@nestjs/core';
import { RedisModule } from '@nestjs/redis';
import { ConfigService } from '@nestjs/config';
@Module({
imports: [
RedisModule.registerAsync({
useFactory: (config: ConfigService) => ({
url: config.get<string>('REDIS_URL'),
}),
inject: [ConfigService],
}),
],
providers: [],
})
export class AppModule {}
接着,创建一个缓存拦截器,用于处理缓存逻辑:
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { RedisService } from '@nestjs/redis';
import { map } from 'rxjs/operators';
@Injectable()
export class CacheInterceptor implements NestInterceptor {
constructor(private readonly redisService: RedisService) {}
async intercept(context: ExecutionContext, next: CallHandler): Promise<Observable<any>> {
const key = this.generateCacheKey(context);
const cachedData = await this.redisService.getClient().get(key);
if (cachedData) {
return Observable.of(JSON.parse(cachedData));
}
return next.handle().pipe(
map(data => {
this.redisService.getClient().set(key, JSON.stringify(data));
return data;
}),
);
}
private generateCacheKey(context: ExecutionContext): string {
const request = context.switchToHttp().getRequest();
return `cache:${request.method}:${request.url}`;
}
}
最后,在全局或特定路由上应用这个拦截器:
import { Module, CacheInterceptor } from '@nestjs/common';
@Module({
providers: [
{
provide: APP_INTERCEPTOR,
useClass: CacheInterceptor,
},
],
})
export class AppModule {}
这样,你的NestJS项目就实现了基于Redis的缓存加速功能。
在NestJS项目中使用Redis进行缓存加速是一个常见的性能优化方案。下面我会给出一个完整的实现方案:
- 首先安装必要的依赖:
npm install cache-manager cache-manager-redis-store @types/cache-manager
- 在app.module.ts中配置Redis模块:
import { CacheModule, Module } from '@nestjs/common';
import * as redisStore from 'cache-manager-redis-store';
@Module({
imports: [
CacheModule.register({
store: redisStore,
host: 'localhost', // Redis服务器地址
port: 6379, // Redis端口
ttl: 600, // 默认缓存时间(秒)
}),
],
})
export class AppModule {}
- 在服务中使用缓存:
import { CACHE_MANAGER, Inject, Injectable } from '@nestjs/common';
import { Cache } from 'cache-manager';
@Injectable()
export class AppService {
constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache) {}
async getData() {
const cachedData = await this.cacheManager.get('data_key');
if (cachedData) {
return cachedData;
}
// 模拟从数据库获取数据
const data = await this.fetchFromDatabase();
await this.cacheManager.set('data_key', data, { ttl: 300 }); // 缓存5分钟
return data;
}
private async fetchFromDatabase() {
// 数据库查询逻辑...
}
}
- 在控制器中使用:
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
async getData() {
return this.appService.getData();
}
}
最佳实践建议:
- 为不同的业务数据设置合理的TTL(过期时间)
- 使用有意义的缓存键名,避免冲突
- 考虑使用Redis集群方案提高可用性
- 对于热点数据可以设置更长的缓存时间
- 在数据更新时及时清除相关缓存
这种方式可以显著减少数据库压力,提高API响应速度,特别是对于读取频繁但变化不频繁的数据效果最佳。