Skip to main content

缓存

缓存是一种出色且简单的技术,有助于提高应用程序的性能。它充当临时数据存储,提供高性能的数据访问。

安装

首先安装所需的包:

npm install @nestjs/cache-manager cache-manager
warning

cache-manager 版本 4 使用秒作为 TTL(Time-To-Live)。当前版本的 cache-manager(v5)已切换为使用毫秒。 NestJS 不会转换该值,只会将您提供的 TTL 直接传递给库。换句话说:

  • 如果使用 cache-manager v4,请以秒为单位提供 TTL。
  • 如果使用 cache-manager v5,请以毫秒为单位提供 TTL。
  • 文档引用的是秒,因为 NestJS 发布时针对 cache-manager 版本 4。

内存缓存

Nest 提供了各种缓存存储提供程序的统一 API。内置的缓存存储是一个内存数据存储。 但是,您可以轻松切换到更全面的解决方案,比如 Redis。

为了启用缓存,请导入 CacheModule 并调用其 register() 方法。

import { Module } from '@nestjs/common';
import { CacheModule } from '@nestjs/cache-manager';
import { AppController } from './app.controller';

@Module({
imports: [CacheModule.register()],
controllers: [AppController],
})
export class AppModule {}

与缓存存储交互

要与缓存管理器实例交互,请使用 CACHE_MANAGER 令牌将其注入到您的类中,如下所示:

constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache) {}
tip

Cache 类是从 cache-manager 导入的,而 CACHE_MANAGER 令牌来自 @nestjs/cache-manager 包。

使用 Cache 实例(来自 cache-manager 包)上的 get 方法从缓存中检索项目。 如果缓存中不存在该项,则将返回 null

const value = await this.cacheManager.get('key');

要将项目添加到缓存,请使用 set 方法:

await this.cacheManager.set('key', 'value');

缓存的默认过期时间是 5 秒。

您可以为此特定键手动指定 TTL(以秒为单位的过期时间),如下所示:

await this.cacheManager.set('key', 'value', 1000);

要禁用缓存的过期时间,请将 ttl 配置属性设置为 0:

await this.cacheManager.set('key', 'value', 0);

要从缓存中删除项目,请使用 del 方法:

await this.cacheManager.del('key');

要清除整个缓存,请使用 reset 方法:

await this.cacheManager.reset();

自动缓存响应

warning

在 GraphQL 应用程序中,拦截器分别对每个字段解析器执行。 因此,使用拦截器缓存响应的 CacheModule 将无法正常工作。

要启用自动缓存响应,只需在要缓存数据的位置使用 CacheInterceptor

@Controller()
@UseInterceptors(CacheInterceptor)
export class AppController {
@Get()
findAll(): string[] {
return [];
}
}
warning

只有 GET 端点会被缓存。此外,使用本机响应对象(@Res())注入的 HTTP 服务器路由无法使用缓存拦截器。 有关更多详细信息,请参阅响应映射

为了减少所需的样板代码,您可以将 CacheInterceptor 绑定到所有端点:

import { Module } from '@nestjs/common';
import { CacheModule, CacheInterceptor } from '@nestjs/cache-manager';
import { AppController } from './app.controller';
import { APP_INTERCEPTOR } from '@nestjs/core';

@Module({
imports: [CacheModule.register()],
controllers: [AppController],
providers: [
{
provide: APP_INTERCEPTOR,
useClass: CacheInterceptor,
},
],
})
export class AppModule {}

自定义缓存

所有缓存的数据都有自己的过期时间([TTL](https://en.wikipedia.org/wiki/Time_to_live))。 要自定义默认值,请将选项对象传递给 register() 方法。

CacheModule.register({
ttl: 5, // 秒
max: 10, // 缓存中的最大项目数
});

全局使用模块

当您想在其他模块中使用 CacheModule 时,您需要导入它(与任何 Nest 模块一样)。 或者,通过将选项对象的 isGlobal 属性设置为 true,将其声明为全局模块, 如下所示。 在这种情况下,一旦在根模块(例如,AppModule)中加载了 CacheModule,您将无需在其他模块中导入它。

CacheModule.register({
isGlobal: true,
});

全局缓存覆盖

启用全局缓存时,缓存条目存储在基于路由路径自动生成的 CacheKey 下。 您可以在每个方法基础上覆盖特定的缓存设置(@CacheKey()@CacheTTL()), 允许为各个控制器方法自定义缓存策略。 在使用不同的缓存存储时,这可能最相关。

@Controller()
export class AppController {
@CacheKey('custom_key')
@CacheTTL(20)
findAll(): string[] {
return [];
}
}
tip

@CacheKey()@CacheTTL() 装饰器是从 @nestjs/cache-manager 包导入的。

@CacheKey() 装饰器可以与相应的 @CacheTTL() 装饰器一起使用,也可以反之。 您可以选择只覆盖 @CacheKey() 或仅覆盖 @CacheTTL()。 未使用装饰器覆盖的设置将使用全局注册时的默认值(请参阅自定义缓存)。

WebSockets 和微服务

您还可以将 CacheInterceptor 应用于 WebSocket 订阅者以及微服务的模式(无论使用的是哪种传输方法)。

@CacheKey('events')
@UseInterceptors(CacheInterceptor)
@SubscribeMessage('events')
handleEvent(client: Client, data: string[]): Observable<string[]> {
return [];
}

然而,为了指定用于随后存储和检索缓存数据的键,需要额外的 @CacheKey() 装饰器。 此外,请注意,不应缓存所有内容。 执行一些业务操作而不仅仅是查询数据的操作不应该被缓存。

此外,您还可以使用 @CacheTTL() 装饰器指定缓存的过期时间(TTL),该装饰器将覆盖全局默认的 TTL 值。

@CacheTTL(10)
@UseInterceptors(CacheInterceptor)
@SubscribeMessage('events')
handleEvent(client: Client, data: string[]): Observable<string[]> {
return [];
}
tip

@CacheTTL() 装饰器可以与或不使用相应的 @CacheKey() 装饰器一起使用。