ホームページ  >  記事  >  ウェブフロントエンド  >  Node.js で Redis を使用するにはどうすればよいですか?それはとても簡単だということがわかりました。

Node.js で Redis を使用するにはどうすればよいですか?それはとても簡単だということがわかりました。

青灯夜游
青灯夜游転載
2022-11-07 20:04:132960ブラウズ

Node で Redis を使用するにはどうすればよいですか?次の記事では、Node.js で Redis を使用する方法を紹介します。とても簡単であることがわかります。お役に立てば幸いです。

Node.js で Redis を使用するにはどうすればよいですか?それはとても簡単だということがわかりました。

前の記事では、実際には redis で最適化できる 2 つの場所を残しました:

  • 1 つは私たちですログイン時に、サーバーは token の生成と、クライアントから JWT を通じて送信された token 情報の検証を実装しています。 [関連チュートリアルの推奨事項: nodejs ビデオ チュートリアル プログラミング ビデオ ]
  • は、データベースに直接いいねデータを書き込むことで、記事にいいねをする機能を実装します

JWTトークン 実装方法は、分散システムの利用を容易にするため、tokenに直接基本情報を入れる方式ですが、期限は設けておりません(可能です)実装されています)、サーバーは token を積極的に無効にすることができません。 Redis は有効期限を当然サポートしており、サーバーが token をアクティブに期限切れにすることもできます。

もちろん、これは JWT トークンが Redis トークンの実装ほど優れていないという意味ではありません。それは使用シナリオによって異なります。ここではどちらが優れているかについては説明しませんが、実装ソリューションを提供するだけです。誰もがそれを実装する方法を知っています。

#1. redis について知る

フロントエンドの友人にとって、Redis は比較的馴染みのないものかもしれません。 #Redis とは何ですか?

#Redis は、オープン ソース (BSD ライセンス) のメモリベースのデータ構造ストレージ システムであり、データベース、キャッシュ、メッセージ ミドルウェアとして使用できます。現在最も人気のある NoSQL データベース。 これには次の特徴があります:

高速速度

単一ノードは 110,000 回/秒の読み取りと 81,000 回/秒の書き込みが可能です
  • メモリに基づいて実行され、高性能
    • C 言語で実装され、オペレーティング システムに近い
    • 永続性
    データ更新は非同期で保存されます。ハードディスク (RDB および AOF
    • ##複数のデータ構造
    • #単純なキー値型データだけでなく、文字列、ハッシュ、リストもサポート、セット、順序付きセット
  • #複数のプログラミング言語などをサポート
    • #Redis の一般的な使用シナリオ
    ##キャッシュ
  • キャッシュは Redis で最もよく使用される機能の 1 つと言えます。合理的なキャッシュにより、アクセスが高速化されるだけでなく、バ​​ックエンド データベースへの負荷も軽減されます。

ランキング システム

Redis リストと順序付きコレクションの特性を利用して、ランキング システムを作成できます。ランキング システムは現在、ショッピング モール、ニュース、ブログ、

カウンター アプリケーション

カウンターのアプリケーションは基本的にランキング システムと同じであり、これはほとんどの Web サイトに共通の要件です。動画 Web サイトの再生回数、電子商取引 Web サイトの再生回数などですが、これらの数値は一般に比較的大きいため、リレーショナル データベースに保存した場合でも、MySQL やその他のリレーショナル データベースにとって大きな課題となります。 Redis は基本的にカウンター アプリケーションを自然にサポートしていると言えます。ライブ ブロードキャスト ルームはすべて、Redis の SortedSet 構造を使用したスト​​レージに適しています。たとえば、集中砲火メッセージは

ZREVRANGEBYSCORE

を使用して並べ替えて返すことができます。Redis5.0 では、新しい

zpopmax

および zpopmin コマンドが追加されました。メッセージ処理がさらに便利になりました。

Redis のアプリケーション シナリオはこれらをはるかに超えています。Redis は、従来のディスク データベースの重要な補足であり、大量の同時アクセスをサポートするインターネット アプリケーションにとって不可欠な基本サービスの 1 つです。

机上で話すのは結局のところ浅いので、練習する必要があります~Redis のインストールと簡単な使用法については紹介しません。ここでは、私が以前に書いた 2 つの記事を紹介します:

Redis のインストール#Redis の使用を開始する - 基本的な使用

Redis のデータ型と一般的に使用されるコマンドを簡単にインストールして理解できます。

##ビジュアル クライアント

RedisClient
    を使用します。 Windows では
  • Redis Desktop Manager##、Mac では #RedisClient のダウンロード リンク: https://github.com/caoxinyu/RedisClient
  • ダウンロード後、# をダブルクリックします。実行する ##redisclient-win32.x86.2.0.exe ファイル

が起動したら、「

server -> add##」をクリックします。

#

接続後、全体の状況を確認できます。

Node.js で Redis を使用するにはどうすればよいですか?それはとても簡単だということがわかりました。

SQL 型のデータとは異なり、redis には新しいデータベースを作成する操作はありません。 16 (0 ~ 15) データベース (デフォルトでは 0 データベースが使用されます)。キーは同じライブラリ内に唯一存在し、重複することはできません。「鍵」のようなもので、「錠」は 1 つしか開けられません。 Key-Value ストレージの本質は、キーを使用して値を識別することです。値を取得する場合は、値に対応するキーを使用して検索する必要があります。

Redis の認識は、この記事の前提条件です。これは、本題に入ります~

この記事では主に Redis を使用してキャッシュ機能を実装します。

#2. Nest.js バージョンで

# を使用する:

#LibraryNest.js

プロジェクトは、Nest.js 8.x バージョンに基づいており、Nest.js 9.x バージョンとは異なります。次の記事では、これらのバージョン間の違いを具体的に整理しています。 V8 から V9 にアップグレードする手順と方法については、ここでは説明しません。

まず、Nest.js プロジェクトで Redis を接続します。Redis の接続に必要なパラメーター:

REDIS_HOST:Redis 域名
REDIS_PORT:Redis 端口号
REDIS_DB: Redis 数据库
REDIS_PASSPORT:Redis 设置的密码

パラメーターを .env.env に書き込みます。 .prod設定ファイル内:

Node.js で Redis を使用するにはどうすればよいですか?それはとても簡単だということがわかりました。

Nest によって公式に推奨されている方法を使用します。必要な手順は 3 つの簡単な手順だけです:

1. 依存関係を導入します。 files

npm install cache-manager --save
npm install cache-manager-redis-store --save
npm install @types/cache-manager -D

Nest さまざまなキャッシュ ストレージに統合された API を提供します。組み込みのデータ ストレージはメモリ内にありますが、cache-manager を使用して他のソリューションを使用してください。たとえば、キャッシュには Redis を使用します。

キャッシュを有効にするには、ConfigModule をインポートし、register() または registerAsync() を呼び出して応答構成パラメーターを渡します。

2. モジュール ファイル src/db/redis-cache.module.ts を作成し、次のように実装します:

import { ConfigModule, ConfigService } from '@nestjs/config';
import { RedisCacheService } from './redis-cache.service';
import { CacheModule, Module, Global } from '@nestjs/common';
import * as redisStore from 'cache-manager-redis-store';

@Module({
  imports: [
    CacheModule.registerAsync({
      isGlobal: true,
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: async (configService: ConfigService) => {
        return {
          store: redisStore,
          host: configService.get('REDIS_HOST'),
          port: configService.get('REDIS_PORT'),
          db: 0, //目标库,
          auth_pass:  configService.get('REDIS_PASSPORT') // 密码,没有可以不写
        };
      },
    }),
  ],
  providers: [RedisCacheService],
  exports: [RedisCacheService],
})
export class RedisCacheModule {}
  • CacheModule registerAsyncメソッドは Redis ストア構成を使用して
  • store 'cache-manager-redis-store' ライブラリを示す属性値 redisStore
  • ##AppModule
  • RedisCacheModule をインポートするとき、 #isGlobal プロパティは true に設定され、グローバル モジュールとして宣言されます。
  • 設定ファイルにRedisの情報が記述されているため、非同期データの処理には
  • registerAsync()メソッドを使用します静的データの場合は、 register
3 を使用して、新しい

redis-cache.service.ts ファイルを作成し、キャッシュの読み取りおよび書き込み

import { Injectable, Inject, CACHE_MANAGER } from '@nestjs/common';
import { Cache } from 'cache-manager';

@Injectable()
export class RedisCacheService {
  constructor(
    @Inject(CACHE_MANAGER)
    private cacheManager: Cache,
  ) {}

  cacheSet(key: string, value: string, ttl: number) {
    this.cacheManager.set(key, value, { ttl }, (err) => {
      if (err) throw err;
    });
  }

  async cacheGet(key: string): Promise<any> {
    return this.cacheManager.get(key);
  }
}
# を実装できます。サービス内の ## 接続 ダウンして、

app.module.ts

RedisCacheModule をインポートします。

トークンの発行と検証プロセスを調整する

Redis を使用して、トークンの有効期限処理、自動トークン更新、および一意のユーザー ログインを実装します。

有効期限処理: ユーザー情報とトークンを redis に配置し、有効期限を設定します。
  • トークンの自動更新: トークンの有効期限は 30 分です (30 分以内の場合)。操作が無い場合は、再度ログインしてください。使用中の切断を防ぐため、30分以内に操作があった場合、トークンは自動的に更新されます。
  • 各ユーザーに固有のログイン: 同じアカウント、別のコンピューターへのログイン、最初にログインしたユーザーは、後でログインしたユーザーによってオフラインにプッシュされます
トークンの有効期限の処理

ログイン後 このとき、jwtで生成したトークンをredisに格納し、有効期限を30分に設定します。 redis に格納される key はユーザー情報で構成され、value はトークン値です。

// auth.service.ts
 async login(user: Partial<User>) {
    const token = this.createToken({
      id: user.id,
      username: user.username,
      role: user.role,
    });

+   await this.redisCacheService.cacheSet(
+     `${user.id}&${user.username}&${user.role}`,
+     token,
+     1800,
+   );
    return { token };
 }

トークンを検証する場合は、redis からトークンを取得してください。トークンが取得できない場合は、トークンの有効期限が切れている可能性があります。

// jwt.strategy.ts
+ import { RedisCacheService } from &#39;./../core/db/redis-cache.service&#39;;

export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor(
    @InjectRepository(User)
    private readonly userRepository: Repository<User>,
    private readonly authService: AuthService,
    private readonly configService: ConfigService,
+   private readonly redisCacheService: RedisCacheService,
  ) {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      secretOrKey: configService.get(&#39;SECRET&#39;),
+     passReqToCallback: true,
    } as StrategyOptions);
  }

  async validate(req, user: User) {
+   const token = ExtractJwt.fromAuthHeaderAsBearerToken()(req);
+   const cacheToken = await this.redisCacheService.cacheGet(
+     `${user.id}&${user.username}&${user.role}`,
+   );
+   if (!cacheToken) {
+     throw new UnauthorizedException(&#39;token 已过期&#39;);
+   }
    const existUser = await this.authService.getUser(user);
    if (!existUser) {
      throw new UnauthorizedException(&#39;token不正确&#39;);
    }
    return existUser;
  }
}

ユーザーのみのログイン

ユーザーがログインすると、発行された新しいトークンが以前のトークンを上書きし、redis 内のトークンと受信リクエストがトークンであるかどうかを判断します。同じでしょうか?そうでない場合は、ユーザーが別の場所でログインしており、トークン エラーが表示されている可能性があります。

// jwt.strategy.ts
  async validate(req, user: User) {
    const token = ExtractJwt.fromAuthHeaderAsBearerToken()(req);
    const cacheToken = await this.redisCacheService.cacheGet(
      `${user.id}&${user.username}&${user.role}`,
    );
    if (!cacheToken) {
      throw new UnauthorizedException(&#39;token 已过期&#39;);
    }
+   if (token != cacheToken) {
+     throw new UnauthorizedException(&#39;token不正确&#39;);
+   }
    const existUser = await this.authService.getUser(user);
    if (!existUser) {
      throw new UnauthorizedException(&#39;token不正确&#39;);
    }
    return existUser;
  }

トークンの自動更新

多くの実装ソリューションがあり、

access_token (jwt は 30 分間有効) と を生成できます。背景 jwt refresh_tokenrefresh_token の有効期間は access_token よりも長くなります。クライアントはこれら 2 つのトークンをキャッシュします。access_token の有効期限が切れると、クライアントは ## を保持します。 # 再度、refresh_token新しい access_token を取得します。この解決策には、インターフェイス呼び出しの開発者の協力が必要です。 ここではピュアバックエンドで実装したトークンの自動更新を中心に紹介します

実装プロセス:

①: jwtがトークンを生成する際の有効期限は [有効期限なし] に設定されています。
  • ②: Redis がトークンをキャッシュするときに有効期間を 30 分に設定します。
  • ③: ユーザーがトークン リクエストを送信するとき、キーが存在し、値が同様に、有効期間は 30 分にリセットされます
  • jwt によって生成されたトークンが期限切れにならないように設定します。コードのこの部分は
auth.module.ts## にあります。 # ファイル。理解できない場合は、記事

Nest.js 実践シリーズ パート 2 - 登録、スキャン コード ログイン、JWT 認証の実装

// auth.module.ts
const jwtModule = JwtModule.registerAsync({
  inject: [ConfigService],
  useFactory: async (configService: ConfigService) => {
    return {
      secret: configService.get(&#39;SECRET&#39;, &#39;test123456&#39;),
-     signOptions: { expiresIn: &#39;4h&#39; },  // 取消有效期设置
    };
  },
});
を読んでから、使用されている cache-manager

が直接更新されていないため、トークン認証が通過した後の有効期限です。 有効期間メソッドは、リセットすることで実装されます:

// jwt.strategy.ts
 async validate(req, user: User) {
    const token = ExtractJwt.fromAuthHeaderAsBearerToken()(req);
    const cacheToken = await this.redisCacheService.cacheGet(
      `${user.id}&${user.username}&${user.role}`,
    );
    if (!cacheToken) {
      throw new UnauthorizedException(&#39;token 已过期&#39;);
    }
    if (token != cacheToken) {
      throw new UnauthorizedException(&#39;token不正确&#39;);
    }
    const existUser = await this.authService.getUser(user);
    if (!existUser) {
      throw new UnauthorizedException(&#39;token不正确&#39;);
    }
+   this.redisCacheService.cacheSet(
+     `${user.id}&${user.username}&${user.role}`,
+     token,
+     1800,
+   );
    return existUser;
  }
この時点で、トークンの有効期限処理は、トークンの自動更新、ユーザーのみのログインはNestで完了します。ログアウト時にトークンを削除する方が簡単です。コードを1つずつ示します。

Nest で公式に推奨されている方法を使用することに加えて、

nestjs-redis

を使用して実装することもできます。トークンを保存したい場合は、

を保存します。 cache-manager-redis-store を使用すると、hash 値の保存および取得メソッドがないことがわかります (これを見つけるには多少の労力がかかります) )。 <blockquote><p>注: <code>nest-redis を使用して Redis キャッシュを実装すると、Nest.js 8 バージョンでエラーが報告されます。友人は @chenjm/nestjs-redis# を使用できます。 # # 代わりに、または問題の解決策を参照してください: Nest 8 redis bug

概要

ソースコードのアドレス: https://github.com/koala-coding/nest-blog

その他のプログラミング関連知識については、

プログラミング教育をご覧ください。 !

Version
V8.1.2

以上がNode.js で Redis を使用するにはどうすればよいですか?それはとても簡単だということがわかりました。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjuejin.cnで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。