Nestjs项目实战 使用Redis进行缓存加速

在Nestjs项目中使用Redis进行缓存加速时遇到了几个问题想请教:

  1. 有没有推荐的在Nestjs中集成Redis的最佳实践方案?官方文档的@nestjs/cache-manager感觉不够详细
  2. 缓存数据时如何设置合理的TTL?不同类型的业务数据(如用户信息、商品列表)应该分别设置多久?
  3. 遇到缓存穿透问题时有什么好的解决方案?布隆过滤器在Nestjs中具体怎么实现?
  4. 项目需要先查Redis再查数据库,现在的代码耦合度较高,有没有优雅的装饰器或拦截器实现方案?
  5. 本地开发时用Docker跑Redis服务,但部署到线上环境后性能反而下降了,可能是什么原因?

3 回复

在NestJS中使用Redis进行缓存加速,首先需要安装@nestjs/redisioredis包:

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/redisioredis

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进行缓存加速是一个常见的性能优化方案。下面我会给出一个完整的实现方案:

  1. 首先安装必要的依赖:
npm install cache-manager cache-manager-redis-store @types/cache-manager
  1. 在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 {}
  1. 在服务中使用缓存:
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() {
    // 数据库查询逻辑...
  }
}
  1. 在控制器中使用:
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();
  }
}

最佳实践建议:

  1. 为不同的业务数据设置合理的TTL(过期时间)
  2. 使用有意义的缓存键名,避免冲突
  3. 考虑使用Redis集群方案提高可用性
  4. 对于热点数据可以设置更长的缓存时间
  5. 在数据更新时及时清除相关缓存

这种方式可以显著减少数据库压力,提高API响应速度,特别是对于读取频繁但变化不频繁的数据效果最佳。

回到顶部