使用Nestjs和Redis探索缓存
#typescript #redis #nestjs #caching

在本教程中,我们将与Nestjs和Redis一起探索缓存的世界。

在我们深入介入Redis之前,Nestjs提供了可以用作内存数据存储的内存中缓存 redis。

为了开始,您可以为此构造此github repository。请确保您选择基本分支,因为它包含本教程的基本应用程序设置。

设置基本应用程序设置后,您可以继续安装cache-manager软件包及其依赖项。

npm install @nestjs/cache-manager cache-manager

,如果您熟悉Nestjs内存中缓存实现,则当前对Cache-Manager有一个更新,我们在本教程中使用版本5。与版本4相反,版本5现在提供 ttl(寿命),以毫秒提供。我们必须进行转换,然后将其解析为Nestjs,因为Nestjs不为我们进行转换。

要启用缓存,我们必须将CacheModule导入到app.module.ts文件中。

import { Module } from '@nestjs/common';  
import { AppController } from './app.controller';  
import { AppService } from './app.service';  
import { MongooseModule } from '@nestjs/mongoose';  
import { ContactModule } from './contact/contact.module';  
import { CacheModule } from '@nestjs/cache-manager';  

@Module({  
  imports: [  
  // mongodb://127.0.0.1:27017/nest-redis - use env variables or other secure options in production
    MongooseModule.forRoot('mongodb://127.0.0.1:27017/nest-redis', {  
      useNewUrlParser: true,  
    }),    ContactModule,  
    CacheModule.register(),  
  ],  controllers: [AppController],  
  providers: [AppService],  
})  
export class AppModule {}

我们的app.module.ts文件应该看起来像上面的文件。

我们还将将其导入我们的Contact模块。在Nestjs中的任何功能模块中,都需要分别将cache-manager导入其中。如果您有一个不需要缓存的模块,那么这不是必需的。

我们的contact.module.ts应该类似于下面的代码块:

import { Module } from '@nestjs/common';  
import { ContactService } from './contact.service';  
import { ContactController } from './contact.controller';  
import { MongooseModule } from '@nestjs/mongoose';  
import { ContactSchema } from './schemas/schema';  
import { CacheModule } from '@nestjs/cache-manager';  

@Module({  
  imports: [  
    MongooseModule.forFeature([{ name: 'Contact', schema: ContactSchema }]),  
    CacheModule.register(),  
  ],  providers: [ContactService],  
  controllers: [ContactController],  
})  
export class ContactModule {}

一个很好的替代方法是为 cachemodule.register()设置isGlobal选项。如果您需要在所有模块上进行缓存可用性,则可以考虑此选项。

让我们继续前往我们的Contact controller,以修改我们现有的一些终点。对于@Get('contacts/:contactId')端点,我们要在调用该方法之前检查我们的response是否在缓存中。使用@useInterceptors装饰器可以实现:

我们的getContact方法应与以下相似:

@UseInterceptors(CacheInterceptor) // Automatically cache the response for this endpoint  
@Get('contacts/:contactId')  
async getContact(  
  @Res() res,  
  @Param('contactId') contactId,  
) {  
  const contact = await this.contactService.getContact(contactId);  
  if (!contact) throw new NotFoundException('Contact does not exist');  
  return res.status(HttpStatus.OK).json(contact);  
}

要注意的事情:

  • 到期时间为5秒
  • 拦截器根据路由路径为缓存条目的缓存键自动化。 这两个选项都可以有效地控制并超越。

实施替代,我们的getContact将是:

@UseInterceptors(CacheInterceptor) // Automatically cache the response for this endpoint  
@CacheKey('getcontact-key')  
@CacheTTL(60000) // now in milliseconds (1 minute === 60000)
@Get('contacts/:contactId')  
async getContact(  
  @Res() res,  
  @Param('contactId') contactId,  
) {  
  const contact = await this.contactService.getContact(contactId);  
  if (!contact) throw new NotFoundException('Contact does not exist');  
  return res.status(HttpStatus.OK).json(contact);  
}
  • 根据官方的Nestjs文档,Cachemodule将无法与GraphQl应用程序正确使用*

现在redis

根据the official Redis website,Redis是开源,内存数据结构存储,用作数据库,缓存,消息代理和流引擎。

Redis进行了调查

要使用redis而不是内存缓存,我们需要安装相关的软件包:

npm i --save cache-manager-redis-yet

此软件包是用于将配置传递给node_redis软件包的nestjs包装器。现在,我们可以更改app.module.ts的某些配置以使用redis。

注意:暂停了cache-manager-redis-store,以允许我们刚安装的软件包。我们安装的此packagetracked directly by the koude19 team

import { Module } from '@nestjs/common';  
import { AppController } from './app.controller';  
import { AppService } from './app.service';  
import { MongooseModule } from '@nestjs/mongoose';  
import { ContactModule } from './contact/contact.module';  
import { CacheModule } from '@nestjs/cache-manager';  
import { redisStore } from 'cache-manager-redis-yet';  

@Module({  
  imports: [  
    MongooseModule.forRoot('mongodb://127.0.0.1:27017/nest-redis', {  
      useNewUrlParser: true,  
    }),  
    CacheModule.registerAsync({  
      isGlobal: true,  
      useFactory: async () => ({  
        store: await redisStore({  
          socket: {  
            host: 'localhost',  
            port: 6379,  
          },        
        }),      
      }),    
    }),    
    ContactModule,  
  ],  controllers: [AppController],  
  providers: [AppService],  
})  
export class AppModule {}

这使我们能够添加新的config options
REDISSTORE:代表node-cache-manager-redis-yet我们刚刚安装
主机和端口设置为默认值

,您还没有运行REDIS服务器,您可以为操作系统查找各种安装方法或考虑Docker选项

前往我们的contact.controller页面,我们可以配置我们的getContact方法,以检查在查询主数据库之前是否有一个缓存的数据。如果存在,我们想返回其他我们想在查询数据库后设置它。

我们的getContact应该与以下相似:

@Get('contacts/:contactId')  
async getContact(@Res() res, @Param('contactId') contactId) {  
  const cachedData = await this.cacheService.get(contactId.toString());  
  if (cachedData) {  
    console.log('Getting data from cache');  
    return res.status(HttpStatus.OK).json(cachedData);  
  }  
  const contact = await this.contactService.getContact(contactId);  
  if (!contact) throw new NotFoundException('Contact does not exist');  
  await this.cacheService.set(contactId.toString(), contact);  
  const newCachedData = await this.cacheService.get(contactId.toString());
  console.log('data set to cache', newCachedData);  
  return res.status(HttpStatus.OK).json(contact);  
}

让我们简要介绍上述代码块:

const cachedData = await this.cacheService.get(contactId.toString());  
  if (cachedData) {  
    console.log('Getting data from cache');  
    return res.status(HttpStatus.OK).json(cachedData);  
  }  

cachedData变量正在检查我们是否有现有缓存,如果存在,则可以检查记录器,并且您将获得从cache
获取数据

await this.cacheService.set(contactId.toString(), contact);  
  const newCachedData = await this.cacheService.get(contactId.toString());
  console.log('data set to cache', newCachedData);  

如果我们的数据在缓存中不存在,则上面的代码块可以帮助我们设置在缓存中。

您的缓存数据现在将持续到您的本地redis服务器。

您可以测试端点,您应该得到与我在记录器中输出相似的结果:

[Nest] 3720  - 05/09/2023, 10:00:49 AM     LOG [NestApplication] Nest application successfully started +5ms
data set to cache {
  _id: '6459510cfc398baa01998a66',
  first_name: 'Daniel',
  last_name: 'Olabemiwo',
  email: 'dee@gmail.com',
  phone: '+23832101',
  message: 'Welcome to this side',
  __v: 0
}

您可以通过将请求发送到使用缓存的Nestjs App中的请求来确认您选择的GUI(我喜欢TablePlus),并且您将看到数据已持续:

Redis on TablePlus

恭喜,您刚刚在Nestjs应用程序中添加了Redis Cache。

在本教程中,我们已成功地向我们的Nestjs应用程序添加了Redis Cache。
REDIS启用较低的应用程序延迟和非常高的数据访问。这使软件工程师可以构建高性能,可靠的解决方案。

就是这样!你怎么认为?在下面的评论中让我知道。