Trung  Nguyen

Trung Nguyen

1658628000

Cách Thêm Bộ Đệm Redis Vào Ứng Dụng NestJS

Hiệu suất, hiệu suất, hiệu suất! Đó là toàn bộ điểm của bộ nhớ đệm.

Bộ nhớ đệm đặc biệt giúp tăng tốc hiệu suất của ứng dụng, do đó cải thiện đáng kể hiệu quả của ứng dụng.

Bài viết này sẽ xem xét cách thêm chức năng bộ nhớ đệm vào ứng dụng NestJS với Redis. Chúng ta sẽ nói về bộ nhớ đệm là gì, về Redis và xem xét quá trình triển khai.

Vì vậy, hãy lấy một tách cà phê (hoặc bất cứ thứ gì bạn thường uống trong những ngày này). Đây sẽ là một điều thú vị!

Bộ nhớ đệm là gì?

Trong máy tính, bộ nhớ đệm là một kho lưu trữ tạm thời, được truy vấn thường xuyên của các dữ liệu trùng lặp. Dữ liệu được lưu giữ ở vị trí dễ truy cập để giảm độ trễ.

Hãy để tôi hình thành một phép loại suy để giúp giải thích khái niệm này tốt hơn…

Giả sử bạn đã lấy được tách cà phê đó sau cùng! Hãy tưởng tượng rằng mỗi lần bạn uống một chút nó, bạn phải quay trở lại máy pha cà phê của mình. Bạn đổ đầy cốc của mình, nhấp một ngụm, và để nó ở đó để quay trở lại máy trạm của bạn và tiếp tục đọc bài viết này.

Bởi vì bạn phải tiếp tục quay đi quay lại máy pha cà phê và tách cà phê của mình, bạn sẽ mất vài giờ để hoàn thành cốc cà phê của mình (và bài viết này). Đây là những gì xảy ra mà không có bộ nhớ đệm.

Hãy tưởng tượng một kịch bản khác. Giả sử khi bạn đến máy pha cà phê để nhấp ngụm cà phê đầu tiên, thay vì nhấp một ngụm và quay trở lại không gian làm việc của mình, bạn đổ đầy cốc và quay trở lại máy trạm với nó trong tay.

Khi bạn tiếp tục đọc bài viết này, bạn luôn có cà phê tại bàn làm việc của mình. Bạn có thể nhanh chóng nhấp một ngụm (độ trễ thấp hơn) để có thể tập trung vào bài viết này và hoàn thành bài viết nhanh hơn nhiều. Đây là những gì sẽ xảy ra khi bộ nhớ đệm được triển khai .

Nếu chúng ta đưa sự tương tự này vào thế giới thực, máy pha cà phê là máy chủ web và bản thân cà phê là dữ liệu thường xuyên được truy vấn.

Redis là gì?

Theo trang web chính thức của Redis , “Redis là một kho lưu trữ cấu trúc dữ liệu trong bộ nhớ mã nguồn mở, được sử dụng làm cơ sở dữ liệu, bộ nhớ cache, môi giới tin nhắn và công cụ phát trực tuyến.”

Điều quan trọng cần lưu ý là Redis không xử lý bộ nhớ đệm một mình . Nó cung cấp các cấu trúc dữ liệu như băm, tập hợp, chuỗi, danh sách, bitmap và tập hợp được sắp xếp với các truy vấn phạm vi, luồng, HyperLogLogs và chỉ mục không gian địa lý.

Triển khai bộ nhớ cache Redis trong ứng dụng NestJS

Điều kiện tiên quyết

Để làm theo bài viết này, bạn sẽ cần những thứ sau:

  • Node.js đã được cài đặt trên máy tính của bạn
  • Kiến thức cơ bản về JavaScript và Node.js
  • NestJS Command Line Interface (CLI) được cài đặt trên máy tính của bạn
  • Hiểu biết cơ bản về cách Nest hoạt động

Nếu bạn chưa cài đặt NestJS, điều này sẽ giúp bạn bắt kịp tốc độ .

Sau khi bạn đã cài đặt NestJS CLI trên máy của mình, hãy tiếp tục và thiết lập bộ đệm Redis cho ứng dụng của chúng tôi.

Thiết lập bộ nhớ cache Redis cho ứng dụng NestJS của chúng tôi

Đầu tiên, hãy tạo một dự án mới. Chúng tôi sẽ gọi nó redis-setup. Mở thiết bị đầu cuối sau khi cài đặt NestJS và chạy dòng mã dưới đây:

nest new redis-setup

Sau đó, chúng tôi muốn chọn trình quản lý gói ưa thích của mình.

Ảnh chụp màn hình trình quản lý gói

Trong trường hợp của tôi, tôi đã chọn npmnhưng hãy chọn cái nào phù hợp với bạn! Sau đó, quá trình cài đặt sẽ tiếp tục.

Sau khi cài đặt xong, chúng ta sẽ thấy một cái gì đó tương tự như ảnh chụp màn hình bên dưới. Chúng tôi phải cdvào ứng dụng của mình bằng cách chạy cd redis-setup.

Ảnh chụp màn hình cài đặt Cd Into Redis

Khi vào trong thư mục dự án, chúng tôi sẽ chạy codetrong terminal. Thao tác này sẽ tự động mở dự án trong VS Code, miễn là nó đã được cài đặt.

Mã VS

Dưới đây là những gì redis-setupdự án của chúng tôi trông như thế nào.

Ảnh chụp màn hình dự án thiết lập Redis

Trước khi chúng tôi tiếp tục thiết lập của mình, có bốn gói chính mà chúng tôi cần cài đặt trong ứng dụng của mình.

Cài đặt các gói

Gói đầu tiên chúng ta cần cài đặt là node-cache-manager. Trình quản lý mô-đun bộ nhớ cache Node cho phép dễ dàng gói các chức năng trong bộ nhớ cache, bộ nhớ đệm theo tầng và một giao diện nhất quán. Cài đặt điều này bằng cách chạy npm install cache-managertrong thiết bị đầu cuối.

Tiếp theo, chúng ta cần cài đặt @types/cache-manager, triển khai TypeScript của node-cache-manager. Cài đặt điều này bằng cách chạy npm i @types/cache-managertrong thiết bị đầu cuối.

Thứ ba, chúng tôi sẽ cài đặt cache-manager-redis-store. Gói này cung cấp một trình bao bọc rất dễ dàng để truyền cấu hình cho node_redisgói. Cài đặt cái này bằng cách chạy npm install cache-manager-redis-store --savetrong thiết bị đầu cuối

Cuối cùng, chúng ta cần cài đặt @types/cache-manager-redis-store. Đây là triển khai TypeScript của cache-manager-redis-storegói. Cài đặt điều này bằng cách chạy npm i --save-dev @types/cache-manager-redis-storetrong thiết bị đầu cuối.

Sau khi hoàn tất quá trình cài đặt, chúng ta có thể tiến hành cấu hình redis-cachecho ứng dụng của mình.

Cấu hìnhredis-cache

Bước đầu tiên để cấu hình redis-cachelà nhập CacheModulevà gọi phương thức của nó register(). Phương pháp này sẽ sử dụng các cấu hình Redis của chúng tôi.

//import CacheModule from @nestjs/common'

import { Module, CacheModule } from '@nestjs/common';

Trong của chúng ta register(), lấy một đối tượng, chúng ta sẽ tạo một thuộc tính được gọi storevà gán redisStorecho nó. Biểu redisStoretượng sẽ đại diện cho cache-manager-redis-storethư viện mà chúng tôi đã cài đặt.

//import CacheModule from '@neskjs/common/cache';
import { Module, CacheModule } from '@nestjs/common';

//import redisStore from 'cache-manager-redis-store';
import * as redisStore from 'cache-manager-redis-store';

import { AppController } from './app.controller';
import { AppService } from './app.service';

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

Tiếp theo, chúng ta sẽ thiết lập một thuộc tính khác trong register()đối tượng phương thức. Chúng tôi sẽ thêm một thuộc tính khác được gọi là hostvà đặt giá trị của nó thành mặc định localhost. Chúng tôi sẽ đặt portgiá trị mặc định là 6379.

//import CacheModule from '@neskjs/common/cache';
import { Module, CacheModule } from '@nestjs/common';

//import redisStore from 'cache-manager-redis-store';
import * as redisStore from 'cache-manager-redis-store';

import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
  imports: [CacheModule.register({ 
    store: redisStore, 
    host: 'localhost', //default host
    port: 6379 //default port
  })],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

Với những điều trên, chúng tôi đã thiết lập một cấu hình cơ bản, đơn giản giữa Redis và ứng dụng NestJS của chúng tôi!

Bước thứ hai là đưa chức năng vào bộ điều khiển của chúng tôi. Điều này để bộ điều khiển của chúng tôi có thể giao tiếp với cửa hàng Redis. Chúng ta cần phải tiêm CacheManager.

Trong thư mục dự án của chúng tôi, hãy đi tới app.controller.ts. GetTrong tệp này , chúng tôi sẽ nhập InjectCACHE_MANAGERtừ @nestjs/common.

//importing Get, Inject, Inject, and CACHE_MANAGER from nestjs/common
import { Controller, Get, Inject, CACHE_MODULE } from '@nestjs/common';

Sau đó, chúng tôi sẽ chuyển vào InjectCACHE_MANAGERmã thông báo. Tiếp theo, chúng tôi sẽ nhập Cachetừ cache-managervà chuyển nó cho của chúng tôi cacheManager.

//importing Get, Inject, Inject, and CACHE_MANAGER from nestjs/common
import { Controller, Get, Inject, CACHE_MANAGER } from '@nestjs/common';
//import the cache manager
import Cache from 'cache-manager';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache{}

  @Get()
  getHello(): string {
    return this.appService.getHello();
  }
}

NB , CacheLớp được nhập từ cache-managerthư viện, trong khi CACHE_MANAGERmã thông báo được nhập từ @nestjs/common.

Việc CACHE_MANAGERđưa vào redis-cache-store, while Cachecung cấp phương thức mặc định để Cachegiao tiếp và cũng hoạt động với bất kỳ cửa hàng nào khác.

Hãy cùng tìm hiểu các phương pháp getvà cách setthức của Redis store.

getsetphương pháp

Cachedụ có getphương thức mà chúng ta có từ cache-managergói. Phương pháp này cho phép chúng tôi lấy các mục từ bộ nhớ cache. nullđược trả về nếu bộ nhớ đệm trống.

let val = await this.cacheManager.get('key');

Chúng tôi sử dụng getphương pháp để thêm một mục vào bộ nhớ cache. Thời gian lưu vào bộ nhớ đệm mặc định là năm giây, nhưng chúng ta có thể đặt thời gian tồn tại (TTL) theo cách thủ công bất cứ lúc nào chúng ta cần. Nó sẽ phụ thuộc vào thông số kỹ thuật của ứng dụng.

await this.cacheManager.set('key', 'value', {ttl: 2000});

Trong getphương pháp của chúng tôi, chúng tôi sẽ chuyển URL để kiểm tra cửa hàng Redis của chúng tôi.

@Get('get-number-cache')

Tiếp theo, trong phần của chúng tôi app.controller.ts, chúng tôi sẽ tạo một phương thức lấy một số. Chúng tôi sẽ kiểm tra xem số của chúng tôi có sẵn trong cửa hàng Redis hay không bằng cách sử dụng chuỗi number.

const val = await this.cacheManager.get('number')
    if(val) {
      return { 
        data: val,
        FromRedis: 'this is loaded from redis cache'
      }
    }

Nếu đúng như vậy, chúng tôi sẽ trả dữ liệu về điểm cuối của chúng tôi. Nhưng, nếu dữ liệu không tồn tại trong redis-stoređó, chúng tôi lưu trữ dữ liệu đó bằng cách sử dụng khóa numbervà đặt TTL thành bất kỳ giá trị mong muốn nào. Trong trường hợp của chúng tôi, chúng tôi sẽ sử dụng 1000.

Cuối cùng, chúng tôi sẽ trả lại dữ liệu được lưu trữ từ cơ sở dữ liệu giả của chúng tôi randomNumDbs. Trong trường hợp này, chúng tôi đang tạo ra con số một cách ngẫu nhiên. Chúng tôi có thể sử dụng một chuỗi, nhưng trong một ứng dụng sản xuất trong thế giới thực, đây là nơi chúng tôi sẽ lấy dữ liệu từ cơ sở dữ liệu cho mọi yêu cầu đầu tiên.

if(!val){
      await this.cacheManager.set('number', this.randomNumDbs , { ttl: 1000 })
      return {
        data: this.randomNumDbs,
        FromRandomNumDbs: 'this is loaded from randomNumDbs'
    }

Dưới đây là mã hoàn chỉnh:

@Controller()
export class AppController {
  //This would be our dummy database since we won't be connecting to a database in the article
  randomNumDbs = Math.floor(Math.random() * 10)
  constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache) {}

  @Get('get-number-cache')
  async getNumber(): Promise<any> {
    const val = await this.cacheManager.get('number')
    if(val) {
      return { 
        data: val,
        FromRedis: 'this is loaded from redis cache'
      }
    }

    if(!val){
      await this.cacheManager.set('number', this.randomNumDbs , { ttl: 1000 })
      return {
        data: this.randomNumDbs,
        FromRandomNumDbs: 'this is loaded from randomNumDbs'
    }
  }
}

Bây giờ đã đến lúc chạy ứng dụng của chúng tôi và kiểm tra những gì chúng tôi đã làm cho đến nay. Để thực hiện việc này trong terminal, hãy chạy npm startvà truy cập URL http: // localhost: 3000 / get-number-cache trong trình duyệt.

Trong lần tải đầu tiên của chúng tôi, yêu cầu của chúng tôi sẽ được lấy từ cơ sở dữ liệu số ngẫu nhiên, giả của chúng tôi.

Yêu cầu cơ sở dữ liệu số ngẫu nhiên

Yêu cầu thứ hai (và các yêu cầu khác) sẽ tải từ cửa hàng Redis cho đến khi dữ liệu được lưu trong bộ nhớ cache hết hạn.

Đã tải Redis Cache

Redis cache cũng có hai phương pháp khác: delreset.

delresetphương pháp

Nếu nó chưa tự giải thích, delphương pháp này sẽ giúp chúng tôi xóa một mục khỏi bộ nhớ cache.

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

Mặt resetkhác, phương pháp này xóa toàn bộ bộ nhớ cache của Redis store

await this.cacheManager.reset();

Thiết lập bộ nhớ đệm tự động bằng Interceptor

Bộ nhớ đệm tự động cho phép bộ đệm ẩn cho mọi Getphương pháp hành động bên trong bộ điều khiển bằng cách sử dụng CacheInterceptor.

Trong app.module.tstệp của chúng tôi, chúng tôi sẽ nhập CacheInterceptor. Định cấu hình hết hạn trên toàn cầu cho bộ nhớ cache tự động của chúng tôi, sử dụng thuộc TTLtính. Để kích hoạt CacheInterceptor, chúng ta cần nhập nó vào mảng providers.

//import CacheModule from '@neskjs/common/cache';
import { Module, CacheModule, CacheInterceptor } from '@nestjs/common';

//import redisStore from 'cache-manager-redis-store';
import * as redisStore from 'cache-manager-redis-store';

import { AppController } from './app.controller';
import { AppService } from './app.service';
import { APP_INTERCEPTOR } from '@nestjs/core';

@Module({
  imports: [CacheModule.register({ 
    store: redisStore, 
    host: 'localhost', //default host
    port: 6379, //default port
    ttl: 2000, //ttl
  })],
  controllers: [AppController],
  providers: [
    {
      provide:APP_INTERCEPTOR,
      useClass: CacheInterceptor
    },
    AppService],
})
export class AppModule {}

Tiếp theo, trong app.controller.ts, chúng tôi nhập UseInterceptorCacheInterceptortừ @nestjs/common.

import { Controller, Get, Inject, CACHE_MANAGER, UseInterceptors, CacheInterceptor } from '@nestjs/common';

Chúng tôi sử dụng trình UseInterceptorstrang trí trực tiếp dưới quyền của chúng tôi @controller()và chuyển CacheInterceptorcho nó. Điều này sẽ cho phép tự động lưu vào bộ nhớ đệm cho tất cả các Getđiểm cuối của chúng tôi bên trong bộ điều khiển.

//importing Get, Inject, Inject, and CACHE_MANAGER from nestjs/common
import {Controller, Get, Inject, CACHE_MANAGER, UseInterceptors, CacheInterceptor} from '@nestjs/common';
//import the cache manager
import {Cache} from 'cache-manager';
import { AppService } from './app.service';
//import Profile.ts
import {User} from './shared/model/User';

@UseInterceptors(CacheInterceptor)
@Controller()
export class AppController {
  fakeModel:User = {
    id: 1,
    name: 'John Doe',
    email: 'okee@gmail.com',
    phone: '123456789',
    address: '123 Main St',
    createdAt: new Date(),
  }

  @Get('auto-caching')
  getAutoCaching() {
    return this.fakeModel;
  }
}

Đối với bộ nhớ đệm tự động, giá trị keyroutegiá trị. Đây là những gì sẽ được lưu trữ trong bộ nhớ cache của chúng tôi, được hiển thị trong ảnh chụp màn hình bên dưới.

Giá trị tuyến đường chính

Chúng tôi có thể xác nhận điều này trong CLI của mình bằng cách nhập keys *lệnh.

Trong trường hợp chúng tôi muốn lưu trữ dữ liệu cho một tuyến đường cụ thể, chúng tôi sẽ không sử dụng timekey. Chúng tôi có thể tùy chỉnh phương pháp của chúng tôi để có một thời gian khác nhau.

Trong app.controller.ts, chúng tôi sử dụng một trình trang trí được gọi là @CacheTTL(). Đối với khóa duy nhất, chúng tôi sử dụng một trình trang trí khác @CacheKey(), được nhập từ @nestjs/common.

//importing Get, Inject, Inject, and CACHE_MANAGER from nestjs/common
import {Controller, Get, Inject, CACHE_MANAGER, UseInterceptors, CacheInterceptor, CacheKey, CacheTTL} from '@nestjs/common';

Chỉ định một chuỗi sẽ lưu dữ liệu vào cửa hàng Redis và thời gian riêng tư cho bộ điều khiển của chúng tôi.

@Get('auto-caching')
  @CacheKey('auto-caching-fake-model')
  @CacheTTL(10)
  getAutoCaching() {
    return this.fakeModel;
  }

Dưới đây là mã hoàn chỉnh cho mã app.controller.tslưu trữ tự động của tệp.

//importing Get, Inject, Inject, and CACHE_MANAGER from nestjs/common
import {Controller, Get, Inject, CACHE_MANAGER, UseInterceptors, CacheInterceptor, CacheKey, CacheTTL} from '@nestjs/common';
//import the cache manager
import {Cache} from 'cache-manager';
import { AppService } from './app.service';
//import Profile.ts
import {User} from './shared/model/User';

@UseInterceptors(CacheInterceptor)
@Controller()
export class AppController {
  fakeModel:User = {
    id: 1,
    name: 'John Doeeee',
    email: 'okee@gmail.com',
    phone: '123456789',
    address: '123 Main St',
    createdAt: new Date(),
  }

  @Get('auto-caching')
  @CacheKey('auto-caching-fake-model')
  @CacheTTL(10)
  getAutoCaching() {
    return this.fakeModel;
  }
}

Sự kết luận

Đó là nó! Trong bài viết này, chúng tôi đã giới thiệu cho các bạn cách thêm bộ đệm Redis vào ứng dụng NestJS.

Redis cho phép độ trễ ứng dụng thấp hơn và truy cập dữ liệu rất cao. Điều này đã cho phép các kỹ sư phần mềm xây dựng các giải pháp hiệu suất cao, đáng tin cậy.

Theo tôi, ưu điểm của Redis nhiều hơn nhược điểm (nếu có). Tôi hy vọng mình đã chia sẻ một số thông tin chuyên sâu về cách NestJS và cửa hàng Redis hoạt động!

Nếu bạn yêu thích bài viết này, hãy bình luận trong phần bình luận! Cảm ơn vì đã ở lại với tôi cho đến cuối bài viết này. Từ biệt!!!

Nguồn: https://blog.logrocket.com/add-redis-cache-nestjs-app/

   #nestjs #redis 

What is GEEK

Buddha Community

Cách Thêm Bộ Đệm Redis Vào Ứng Dụng NestJS
Trung  Nguyen

Trung Nguyen

1658628000

Cách Thêm Bộ Đệm Redis Vào Ứng Dụng NestJS

Hiệu suất, hiệu suất, hiệu suất! Đó là toàn bộ điểm của bộ nhớ đệm.

Bộ nhớ đệm đặc biệt giúp tăng tốc hiệu suất của ứng dụng, do đó cải thiện đáng kể hiệu quả của ứng dụng.

Bài viết này sẽ xem xét cách thêm chức năng bộ nhớ đệm vào ứng dụng NestJS với Redis. Chúng ta sẽ nói về bộ nhớ đệm là gì, về Redis và xem xét quá trình triển khai.

Vì vậy, hãy lấy một tách cà phê (hoặc bất cứ thứ gì bạn thường uống trong những ngày này). Đây sẽ là một điều thú vị!

Bộ nhớ đệm là gì?

Trong máy tính, bộ nhớ đệm là một kho lưu trữ tạm thời, được truy vấn thường xuyên của các dữ liệu trùng lặp. Dữ liệu được lưu giữ ở vị trí dễ truy cập để giảm độ trễ.

Hãy để tôi hình thành một phép loại suy để giúp giải thích khái niệm này tốt hơn…

Giả sử bạn đã lấy được tách cà phê đó sau cùng! Hãy tưởng tượng rằng mỗi lần bạn uống một chút nó, bạn phải quay trở lại máy pha cà phê của mình. Bạn đổ đầy cốc của mình, nhấp một ngụm, và để nó ở đó để quay trở lại máy trạm của bạn và tiếp tục đọc bài viết này.

Bởi vì bạn phải tiếp tục quay đi quay lại máy pha cà phê và tách cà phê của mình, bạn sẽ mất vài giờ để hoàn thành cốc cà phê của mình (và bài viết này). Đây là những gì xảy ra mà không có bộ nhớ đệm.

Hãy tưởng tượng một kịch bản khác. Giả sử khi bạn đến máy pha cà phê để nhấp ngụm cà phê đầu tiên, thay vì nhấp một ngụm và quay trở lại không gian làm việc của mình, bạn đổ đầy cốc và quay trở lại máy trạm với nó trong tay.

Khi bạn tiếp tục đọc bài viết này, bạn luôn có cà phê tại bàn làm việc của mình. Bạn có thể nhanh chóng nhấp một ngụm (độ trễ thấp hơn) để có thể tập trung vào bài viết này và hoàn thành bài viết nhanh hơn nhiều. Đây là những gì sẽ xảy ra khi bộ nhớ đệm được triển khai .

Nếu chúng ta đưa sự tương tự này vào thế giới thực, máy pha cà phê là máy chủ web và bản thân cà phê là dữ liệu thường xuyên được truy vấn.

Redis là gì?

Theo trang web chính thức của Redis , “Redis là một kho lưu trữ cấu trúc dữ liệu trong bộ nhớ mã nguồn mở, được sử dụng làm cơ sở dữ liệu, bộ nhớ cache, môi giới tin nhắn và công cụ phát trực tuyến.”

Điều quan trọng cần lưu ý là Redis không xử lý bộ nhớ đệm một mình . Nó cung cấp các cấu trúc dữ liệu như băm, tập hợp, chuỗi, danh sách, bitmap và tập hợp được sắp xếp với các truy vấn phạm vi, luồng, HyperLogLogs và chỉ mục không gian địa lý.

Triển khai bộ nhớ cache Redis trong ứng dụng NestJS

Điều kiện tiên quyết

Để làm theo bài viết này, bạn sẽ cần những thứ sau:

  • Node.js đã được cài đặt trên máy tính của bạn
  • Kiến thức cơ bản về JavaScript và Node.js
  • NestJS Command Line Interface (CLI) được cài đặt trên máy tính của bạn
  • Hiểu biết cơ bản về cách Nest hoạt động

Nếu bạn chưa cài đặt NestJS, điều này sẽ giúp bạn bắt kịp tốc độ .

Sau khi bạn đã cài đặt NestJS CLI trên máy của mình, hãy tiếp tục và thiết lập bộ đệm Redis cho ứng dụng của chúng tôi.

Thiết lập bộ nhớ cache Redis cho ứng dụng NestJS của chúng tôi

Đầu tiên, hãy tạo một dự án mới. Chúng tôi sẽ gọi nó redis-setup. Mở thiết bị đầu cuối sau khi cài đặt NestJS và chạy dòng mã dưới đây:

nest new redis-setup

Sau đó, chúng tôi muốn chọn trình quản lý gói ưa thích của mình.

Ảnh chụp màn hình trình quản lý gói

Trong trường hợp của tôi, tôi đã chọn npmnhưng hãy chọn cái nào phù hợp với bạn! Sau đó, quá trình cài đặt sẽ tiếp tục.

Sau khi cài đặt xong, chúng ta sẽ thấy một cái gì đó tương tự như ảnh chụp màn hình bên dưới. Chúng tôi phải cdvào ứng dụng của mình bằng cách chạy cd redis-setup.

Ảnh chụp màn hình cài đặt Cd Into Redis

Khi vào trong thư mục dự án, chúng tôi sẽ chạy codetrong terminal. Thao tác này sẽ tự động mở dự án trong VS Code, miễn là nó đã được cài đặt.

Mã VS

Dưới đây là những gì redis-setupdự án của chúng tôi trông như thế nào.

Ảnh chụp màn hình dự án thiết lập Redis

Trước khi chúng tôi tiếp tục thiết lập của mình, có bốn gói chính mà chúng tôi cần cài đặt trong ứng dụng của mình.

Cài đặt các gói

Gói đầu tiên chúng ta cần cài đặt là node-cache-manager. Trình quản lý mô-đun bộ nhớ cache Node cho phép dễ dàng gói các chức năng trong bộ nhớ cache, bộ nhớ đệm theo tầng và một giao diện nhất quán. Cài đặt điều này bằng cách chạy npm install cache-managertrong thiết bị đầu cuối.

Tiếp theo, chúng ta cần cài đặt @types/cache-manager, triển khai TypeScript của node-cache-manager. Cài đặt điều này bằng cách chạy npm i @types/cache-managertrong thiết bị đầu cuối.

Thứ ba, chúng tôi sẽ cài đặt cache-manager-redis-store. Gói này cung cấp một trình bao bọc rất dễ dàng để truyền cấu hình cho node_redisgói. Cài đặt cái này bằng cách chạy npm install cache-manager-redis-store --savetrong thiết bị đầu cuối

Cuối cùng, chúng ta cần cài đặt @types/cache-manager-redis-store. Đây là triển khai TypeScript của cache-manager-redis-storegói. Cài đặt điều này bằng cách chạy npm i --save-dev @types/cache-manager-redis-storetrong thiết bị đầu cuối.

Sau khi hoàn tất quá trình cài đặt, chúng ta có thể tiến hành cấu hình redis-cachecho ứng dụng của mình.

Cấu hìnhredis-cache

Bước đầu tiên để cấu hình redis-cachelà nhập CacheModulevà gọi phương thức của nó register(). Phương pháp này sẽ sử dụng các cấu hình Redis của chúng tôi.

//import CacheModule from @nestjs/common'

import { Module, CacheModule } from '@nestjs/common';

Trong của chúng ta register(), lấy một đối tượng, chúng ta sẽ tạo một thuộc tính được gọi storevà gán redisStorecho nó. Biểu redisStoretượng sẽ đại diện cho cache-manager-redis-storethư viện mà chúng tôi đã cài đặt.

//import CacheModule from '@neskjs/common/cache';
import { Module, CacheModule } from '@nestjs/common';

//import redisStore from 'cache-manager-redis-store';
import * as redisStore from 'cache-manager-redis-store';

import { AppController } from './app.controller';
import { AppService } from './app.service';

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

Tiếp theo, chúng ta sẽ thiết lập một thuộc tính khác trong register()đối tượng phương thức. Chúng tôi sẽ thêm một thuộc tính khác được gọi là hostvà đặt giá trị của nó thành mặc định localhost. Chúng tôi sẽ đặt portgiá trị mặc định là 6379.

//import CacheModule from '@neskjs/common/cache';
import { Module, CacheModule } from '@nestjs/common';

//import redisStore from 'cache-manager-redis-store';
import * as redisStore from 'cache-manager-redis-store';

import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
  imports: [CacheModule.register({ 
    store: redisStore, 
    host: 'localhost', //default host
    port: 6379 //default port
  })],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

Với những điều trên, chúng tôi đã thiết lập một cấu hình cơ bản, đơn giản giữa Redis và ứng dụng NestJS của chúng tôi!

Bước thứ hai là đưa chức năng vào bộ điều khiển của chúng tôi. Điều này để bộ điều khiển của chúng tôi có thể giao tiếp với cửa hàng Redis. Chúng ta cần phải tiêm CacheManager.

Trong thư mục dự án của chúng tôi, hãy đi tới app.controller.ts. GetTrong tệp này , chúng tôi sẽ nhập InjectCACHE_MANAGERtừ @nestjs/common.

//importing Get, Inject, Inject, and CACHE_MANAGER from nestjs/common
import { Controller, Get, Inject, CACHE_MODULE } from '@nestjs/common';

Sau đó, chúng tôi sẽ chuyển vào InjectCACHE_MANAGERmã thông báo. Tiếp theo, chúng tôi sẽ nhập Cachetừ cache-managervà chuyển nó cho của chúng tôi cacheManager.

//importing Get, Inject, Inject, and CACHE_MANAGER from nestjs/common
import { Controller, Get, Inject, CACHE_MANAGER } from '@nestjs/common';
//import the cache manager
import Cache from 'cache-manager';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache{}

  @Get()
  getHello(): string {
    return this.appService.getHello();
  }
}

NB , CacheLớp được nhập từ cache-managerthư viện, trong khi CACHE_MANAGERmã thông báo được nhập từ @nestjs/common.

Việc CACHE_MANAGERđưa vào redis-cache-store, while Cachecung cấp phương thức mặc định để Cachegiao tiếp và cũng hoạt động với bất kỳ cửa hàng nào khác.

Hãy cùng tìm hiểu các phương pháp getvà cách setthức của Redis store.

getsetphương pháp

Cachedụ có getphương thức mà chúng ta có từ cache-managergói. Phương pháp này cho phép chúng tôi lấy các mục từ bộ nhớ cache. nullđược trả về nếu bộ nhớ đệm trống.

let val = await this.cacheManager.get('key');

Chúng tôi sử dụng getphương pháp để thêm một mục vào bộ nhớ cache. Thời gian lưu vào bộ nhớ đệm mặc định là năm giây, nhưng chúng ta có thể đặt thời gian tồn tại (TTL) theo cách thủ công bất cứ lúc nào chúng ta cần. Nó sẽ phụ thuộc vào thông số kỹ thuật của ứng dụng.

await this.cacheManager.set('key', 'value', {ttl: 2000});

Trong getphương pháp của chúng tôi, chúng tôi sẽ chuyển URL để kiểm tra cửa hàng Redis của chúng tôi.

@Get('get-number-cache')

Tiếp theo, trong phần của chúng tôi app.controller.ts, chúng tôi sẽ tạo một phương thức lấy một số. Chúng tôi sẽ kiểm tra xem số của chúng tôi có sẵn trong cửa hàng Redis hay không bằng cách sử dụng chuỗi number.

const val = await this.cacheManager.get('number')
    if(val) {
      return { 
        data: val,
        FromRedis: 'this is loaded from redis cache'
      }
    }

Nếu đúng như vậy, chúng tôi sẽ trả dữ liệu về điểm cuối của chúng tôi. Nhưng, nếu dữ liệu không tồn tại trong redis-stoređó, chúng tôi lưu trữ dữ liệu đó bằng cách sử dụng khóa numbervà đặt TTL thành bất kỳ giá trị mong muốn nào. Trong trường hợp của chúng tôi, chúng tôi sẽ sử dụng 1000.

Cuối cùng, chúng tôi sẽ trả lại dữ liệu được lưu trữ từ cơ sở dữ liệu giả của chúng tôi randomNumDbs. Trong trường hợp này, chúng tôi đang tạo ra con số một cách ngẫu nhiên. Chúng tôi có thể sử dụng một chuỗi, nhưng trong một ứng dụng sản xuất trong thế giới thực, đây là nơi chúng tôi sẽ lấy dữ liệu từ cơ sở dữ liệu cho mọi yêu cầu đầu tiên.

if(!val){
      await this.cacheManager.set('number', this.randomNumDbs , { ttl: 1000 })
      return {
        data: this.randomNumDbs,
        FromRandomNumDbs: 'this is loaded from randomNumDbs'
    }

Dưới đây là mã hoàn chỉnh:

@Controller()
export class AppController {
  //This would be our dummy database since we won't be connecting to a database in the article
  randomNumDbs = Math.floor(Math.random() * 10)
  constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache) {}

  @Get('get-number-cache')
  async getNumber(): Promise<any> {
    const val = await this.cacheManager.get('number')
    if(val) {
      return { 
        data: val,
        FromRedis: 'this is loaded from redis cache'
      }
    }

    if(!val){
      await this.cacheManager.set('number', this.randomNumDbs , { ttl: 1000 })
      return {
        data: this.randomNumDbs,
        FromRandomNumDbs: 'this is loaded from randomNumDbs'
    }
  }
}

Bây giờ đã đến lúc chạy ứng dụng của chúng tôi và kiểm tra những gì chúng tôi đã làm cho đến nay. Để thực hiện việc này trong terminal, hãy chạy npm startvà truy cập URL http: // localhost: 3000 / get-number-cache trong trình duyệt.

Trong lần tải đầu tiên của chúng tôi, yêu cầu của chúng tôi sẽ được lấy từ cơ sở dữ liệu số ngẫu nhiên, giả của chúng tôi.

Yêu cầu cơ sở dữ liệu số ngẫu nhiên

Yêu cầu thứ hai (và các yêu cầu khác) sẽ tải từ cửa hàng Redis cho đến khi dữ liệu được lưu trong bộ nhớ cache hết hạn.

Đã tải Redis Cache

Redis cache cũng có hai phương pháp khác: delreset.

delresetphương pháp

Nếu nó chưa tự giải thích, delphương pháp này sẽ giúp chúng tôi xóa một mục khỏi bộ nhớ cache.

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

Mặt resetkhác, phương pháp này xóa toàn bộ bộ nhớ cache của Redis store

await this.cacheManager.reset();

Thiết lập bộ nhớ đệm tự động bằng Interceptor

Bộ nhớ đệm tự động cho phép bộ đệm ẩn cho mọi Getphương pháp hành động bên trong bộ điều khiển bằng cách sử dụng CacheInterceptor.

Trong app.module.tstệp của chúng tôi, chúng tôi sẽ nhập CacheInterceptor. Định cấu hình hết hạn trên toàn cầu cho bộ nhớ cache tự động của chúng tôi, sử dụng thuộc TTLtính. Để kích hoạt CacheInterceptor, chúng ta cần nhập nó vào mảng providers.

//import CacheModule from '@neskjs/common/cache';
import { Module, CacheModule, CacheInterceptor } from '@nestjs/common';

//import redisStore from 'cache-manager-redis-store';
import * as redisStore from 'cache-manager-redis-store';

import { AppController } from './app.controller';
import { AppService } from './app.service';
import { APP_INTERCEPTOR } from '@nestjs/core';

@Module({
  imports: [CacheModule.register({ 
    store: redisStore, 
    host: 'localhost', //default host
    port: 6379, //default port
    ttl: 2000, //ttl
  })],
  controllers: [AppController],
  providers: [
    {
      provide:APP_INTERCEPTOR,
      useClass: CacheInterceptor
    },
    AppService],
})
export class AppModule {}

Tiếp theo, trong app.controller.ts, chúng tôi nhập UseInterceptorCacheInterceptortừ @nestjs/common.

import { Controller, Get, Inject, CACHE_MANAGER, UseInterceptors, CacheInterceptor } from '@nestjs/common';

Chúng tôi sử dụng trình UseInterceptorstrang trí trực tiếp dưới quyền của chúng tôi @controller()và chuyển CacheInterceptorcho nó. Điều này sẽ cho phép tự động lưu vào bộ nhớ đệm cho tất cả các Getđiểm cuối của chúng tôi bên trong bộ điều khiển.

//importing Get, Inject, Inject, and CACHE_MANAGER from nestjs/common
import {Controller, Get, Inject, CACHE_MANAGER, UseInterceptors, CacheInterceptor} from '@nestjs/common';
//import the cache manager
import {Cache} from 'cache-manager';
import { AppService } from './app.service';
//import Profile.ts
import {User} from './shared/model/User';

@UseInterceptors(CacheInterceptor)
@Controller()
export class AppController {
  fakeModel:User = {
    id: 1,
    name: 'John Doe',
    email: 'okee@gmail.com',
    phone: '123456789',
    address: '123 Main St',
    createdAt: new Date(),
  }

  @Get('auto-caching')
  getAutoCaching() {
    return this.fakeModel;
  }
}

Đối với bộ nhớ đệm tự động, giá trị keyroutegiá trị. Đây là những gì sẽ được lưu trữ trong bộ nhớ cache của chúng tôi, được hiển thị trong ảnh chụp màn hình bên dưới.

Giá trị tuyến đường chính

Chúng tôi có thể xác nhận điều này trong CLI của mình bằng cách nhập keys *lệnh.

Trong trường hợp chúng tôi muốn lưu trữ dữ liệu cho một tuyến đường cụ thể, chúng tôi sẽ không sử dụng timekey. Chúng tôi có thể tùy chỉnh phương pháp của chúng tôi để có một thời gian khác nhau.

Trong app.controller.ts, chúng tôi sử dụng một trình trang trí được gọi là @CacheTTL(). Đối với khóa duy nhất, chúng tôi sử dụng một trình trang trí khác @CacheKey(), được nhập từ @nestjs/common.

//importing Get, Inject, Inject, and CACHE_MANAGER from nestjs/common
import {Controller, Get, Inject, CACHE_MANAGER, UseInterceptors, CacheInterceptor, CacheKey, CacheTTL} from '@nestjs/common';

Chỉ định một chuỗi sẽ lưu dữ liệu vào cửa hàng Redis và thời gian riêng tư cho bộ điều khiển của chúng tôi.

@Get('auto-caching')
  @CacheKey('auto-caching-fake-model')
  @CacheTTL(10)
  getAutoCaching() {
    return this.fakeModel;
  }

Dưới đây là mã hoàn chỉnh cho mã app.controller.tslưu trữ tự động của tệp.

//importing Get, Inject, Inject, and CACHE_MANAGER from nestjs/common
import {Controller, Get, Inject, CACHE_MANAGER, UseInterceptors, CacheInterceptor, CacheKey, CacheTTL} from '@nestjs/common';
//import the cache manager
import {Cache} from 'cache-manager';
import { AppService } from './app.service';
//import Profile.ts
import {User} from './shared/model/User';

@UseInterceptors(CacheInterceptor)
@Controller()
export class AppController {
  fakeModel:User = {
    id: 1,
    name: 'John Doeeee',
    email: 'okee@gmail.com',
    phone: '123456789',
    address: '123 Main St',
    createdAt: new Date(),
  }

  @Get('auto-caching')
  @CacheKey('auto-caching-fake-model')
  @CacheTTL(10)
  getAutoCaching() {
    return this.fakeModel;
  }
}

Sự kết luận

Đó là nó! Trong bài viết này, chúng tôi đã giới thiệu cho các bạn cách thêm bộ đệm Redis vào ứng dụng NestJS.

Redis cho phép độ trễ ứng dụng thấp hơn và truy cập dữ liệu rất cao. Điều này đã cho phép các kỹ sư phần mềm xây dựng các giải pháp hiệu suất cao, đáng tin cậy.

Theo tôi, ưu điểm của Redis nhiều hơn nhược điểm (nếu có). Tôi hy vọng mình đã chia sẻ một số thông tin chuyên sâu về cách NestJS và cửa hàng Redis hoạt động!

Nếu bạn yêu thích bài viết này, hãy bình luận trong phần bình luận! Cảm ơn vì đã ở lại với tôi cho đến cuối bài viết này. Từ biệt!!!

Nguồn: https://blog.logrocket.com/add-redis-cache-nestjs-app/

   #nestjs #redis 

Loma  Baumbach

Loma Baumbach

1596679140

Redis Transactions & Long-Running Lua Scripts

Redis offers two mechanisms for handling transactions – MULTI/EXEC based transactions and Lua scripts evaluation. Redis Lua scripting is the recommended approach and is fairly popular in usage.

Our Redis™ customers who have Lua scripts deployed often report this error – “BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE”. In this post, we will explain the Redis transactional property of scripts, what this error is about, and why we must be extra careful about it on Sentinel-managed systems that can failover.

Redis Lua Scripts Diagram - ScaleGrid Blog

Transactional Nature of Redis Lua Scripts

Redis “transactions” aren’t really transactions as understood conventionally – in case of errors, there is no rollback of writes made by the script.

Atomicity” of Redis scripts is guaranteed in the following manner:

  • Once a script begins executing, all other commands/scripts are blocked until the script completes. So, other clients either see the changes made by the script or they don’t. This is because they can only execute either before the script or after the script.
  • However, Redis doesn’t do rollbacks, so on an error within a script, any changes already made by the script will be retained and future commands/scripts will see those partial changes.
  • Since all other clients are blocked while the script executes, it is critical that the script is well-behaved and finishes in time.

The ‘lua-time-limit’ Value

It is highly recommended that the script complete within a time limit. Redis enforces this in a weak manner with the ‘lua-time-limit’ value. This is the maximum allowed time (in ms) that the script is allowed to run. The default value is 5 seconds. This is a really long time for CPU-bound activity (scripts have limited access and can’t run commands that access the disk).

However, the script is not killed when it executes beyond this time. Redis starts accepting client commands again, but responds to them with a BUSY error.

If you must kill the script at this point, there are two options available:

  • SCRIPT KILL command can be used to stop a script that hasn’t yet done any writes.
  • If the script has already performed writes to the server and must still be killed, use the SHUTDOWN NOSAVE to shutdown the server completely.

It is usually better to just wait for the script to complete its operation. The complete information on methods to kill the script execution and related behavior are available in the documentation.

#cloud #database #developer #high availability #howto #redis #scalegrid #lua-time-limit #redis diagram #redis master #redis scripts #redis sentinel #redis servers #redis transactions #sentinel-managed #server failures

Redis Labs Partners with Microsoft to Deliver a New Redis Cache

In a recent blog post, Microsoft announced a new partnership with Redis Labs to deliver Redis Enterprise as newly, fully integrated tiers of Azure Cache for Redis. The enhanced service offering, currently in private preview, will provide customers with two new Enterprise tiers – which include Redis on Flash, modules, and the ability to create an active geo-redundant cache for hybrid-cloud architectures in the future.

Microsoft started their collaboration with Redis Labs back in 2014 with the launch of Redis Cloud on Azure. Since then the service has evolved with updates such as geo-replication support and reserved-capacity. Now, the public cloud vendor incorporates two existing offerings of Redis Labs as additional Enterprise tiers in Azure Redis Cache service providing customers with more features, higher availability, and security capabilities.

Ofer Bengal, CEO and co-founder of Redis Labs, wrote in his blog post on the new partnership announcement:

Throughout the development process, three key customer drivers were consistently top of mind: improve developer productivity, ensure operational resiliency, and ease cloud migration. Teams at both organizations were committed to building an integration that delivers these values to our customers. With the announcement of Redis Enterprise integration into Azure Cache for Redis, we meet these needs.
With the new tiers, developers can use the most up-to-date version of Redis, including its native data structures, probabilistic data structures, streams, time-series, and search data models. Furthermore, they can benefit from the native integration with other Azure services, and easily deploy a Redis cluster and scale to terabyte-sized data sets at the cost of a disk-based data store by utilizing Redis on Flash technology. Also, with the added support of the Redis modules

RediSearch, RedisTimeSeries, and RedisBloom developers can build applications for a wide variety of use cases with a single technology.

#microsoft azure #clustering & caching #redis #microsoft #cloud #distributed cache #caching #devops #architecture & design #development #news

Lindsey  Koepp

Lindsey Koepp

1602942851

AWS Announces Redis 6 Compatibility to Amazon ElastiCache for Redis

Recently AWS announced Redis 6 compatibility to Amazon ElastiCache for Redis, which brings several new features such as Managed Role-Based Access Control, Client-Side caching and some significant operational improvements.

Earlier this year AWS announced the Global Datastore feature of Amazon ElastiCache for Redis which provides fully-managed, fast, reliable and secure cross-region replication. Moreover, more recent the public cloud vendor improved the ability for customers to monitor their Redis fleet by enabling 18 additional engine and node-level CloudWatch metrics. It also added support for resource-level permission policies - allowing customers to assign AWS Identity and Access Management (IAM) principal permissions to specific ElastiCache resource or resources. And now AWS further enhances the service with Redis 6 compatibility, which brings even more features.

_Source: _https://aws.amazon.com/elasticache

The significant new features that come with the Redis 6 compatibility are:

  • Managed Role-Based Access Control providing users with the ability to create and manage users and user groups that they can use to set up Role-Based Access Control (RBAC) for Redis commands.
  • Client-Side Caching provides server-side enhancements to deliver efficient client-side caching to improve application performance further.
  • Operational Improvements available through several enhancements that improve application availability and reliability, such as improved replication under low memory conditions.

#distributed cache #redis #clustering & caching #cloud #caching #aws #amazon web services #development #architecture & design #devops #news

What is Distributed Caching

In this tutorial we are going to learn about what a cache is ? when we are going to use?, and How to use it? in a detailed manner.

So first of all,

What is a Cache?

Imagine that you have a system like this. Client Application request for some results from the server and the server asks those details form the Database. Then Database pullout the results to the Application server. Without pulling data from the Database all the time we can maintain another database/server to store data called Cache. Here there are 2 scenarios that you might want to use a cache.

  • When you requesting for a commonly used data, and every time we ask for those data we need to provide from the Database. Instead of this, you can save those commonly used data in a cache (in-memory cache). Here we can reduce network calls.
  • When you are doing a calculation by getting data from the database. You can reduce the number of calculations here. Store the result in cache and get the value from the cache without doing recomputations all the time. (Example: Assume you have a Student Management System and you need to calculate the average marks for a particular exam for a particular student. Store Average value in cache memory with key-value pair.)
  • We have all servers and they are hitting the database. It’s going to be a lot of loads. Instead of getting one cache, we can use more caches as a distributed system for Avoid load in the Database.

Can we store all the data in the cache?

No! We can’t store all the data in the cache because of multiple reasons.

  • The hardware that we use to make cache memories is much more expensive than a normal database.
  • If you store a ton of data on cache the search time will increase compared to the database.

So that now you know we can store infinite data on the database and we need to store the most valuable data in the cache.

When do you load data into the cache? When do you evict data from the cache?

Loading or Evicting data from the cache is called a Policy. So the cache performance depends on your cache policy. There are a number of policies you can have. The Most popular one is LRU(Least Recently Used).

**LRU **— you can add recently used entries to the bottom of the cache and least recently used entries go to the bottom. If you want to add new entries but the cache is almost full, then you can evict(kick) out those least recently used data.

Image for post

Some other Policies are,

  • Least Recently Used (LRU)
  • First In First Out (FIFO)
  • Random

#distributed-cache #caching-server #redis #caching