How to use Redis in Node.js? It turns out it's that simple!
How to use Redis in
Node? The following article will introduce to you how to use Redis in Node.js. You will find that it is so simple. I hope it will be helpful to you!
In the previous article, we actually left two places that can be optimized with redis
:
- One is us When logging in, the server has implemented
token
generation and verification of thetoken
information sent by the client throughJWT
. [Related tutorial recommendations: nodejs video tutorial, Programming video] - implements the function of liking articles by writing the like data directly into the database
JWT token
The implementation method is to put the basic information directly in token
to facilitate the use of distributed systems, but we do not set a limited period (this is possible implemented), and the server cannot actively invalidate token
. Redis naturally supports expiration time, and can also allow the server to actively expire token
.
Of course, this does not mean that JWT token is not as good as redis token implementation. It depends on the usage scenario. Here we do not discuss which one is better, but only provide an implementation solution to let everyone know how to implement it.
1. Get to know redis
For front-end friends, Redis may be relatively unfamiliar. First, let’s get to know
What is Redis? What
Redis is an open source (BSD licensed), memory-based data structure storage system. It can be used as a database, cache and message middleware. It is one of the most popular NoSQL databases now. .
It has the following characteristics:
- Fast speed
- A single node can read 110,000 times/s and write 81,000 times/s
- Run based on memory , high performance
- Implemented in C language, closer to the operating system
- Persistence
- Data updates will be asynchronously saved to the hard disk (RDB And AOF
##Multiple data structures - Not only supports simple key-value type data
- It also supports: string, hash, list, Sets, ordered sets
Support multiple programming languages, etc.
Redis typical usage scenarios
Caching
Caching can be said to be one of the most commonly used functions of Redis. Reasonable caching can not only speed up access, but also reduce the pressure on the back-end database.Ranking system
Using the characteristics of Redis lists and ordered collections, a ranking system can be created. The ranking system is currently used in shopping malls, news, blogs, etc. It is indispensable.Counter application
The application of counter is basically the same as the ranking system, which is a common requirement of most websites, such as the play count of video websites, The number of views on e-commerce websites, etc., but these numbers are generally relatively large. If stored in a relational database, it will still pose a great challenge to MySQL or other relational databases, and Redis can basically be said to naturally support counter applications.(Live video) message barrage
The online user list, gift rankings, barrage messages and other information in the live broadcast room are all suitable for storage using the SortedSet structure in Redis .For example, barrage messages can be sorted and returned usingZREVRANGEBYSCORE. In Redis5.0, new
zpopmax and
zpopmin commands are added. More convenient for message processing.
Talking on paper is ultimately shallow, you must practice it~I will not introduce the installation and simple use of Redis one by one here. Here are two articles I wrote before: You can quickly install, understand Redis data types and Commonly used commands.
Visual client
UseRedisClient under Windows, and Redis Desktop Manager## under mac #RedisClient download link: https://github.com/caoxinyu/RedisClient
After downloading, double-click the
redisclient-win32.x86.2.0.exe file to run After
is started, click
After connecting, you can see the overall situation:
Different from SQL-type data, redis does not provide the operation of creating a new database because it comes with 16 (0 -15) databases (0 database is used by default). In the same library, key is the only one that exists and is not allowed to be repeated. It is like a "key" and can only open one "lock". The essence of key-value storage is to use key to identify value. When you want to retrieve value, you must use the key corresponding to value to search.
Redis recognition is a prerequisite for the article. This is the end of the article. Let’s get to the point~
This article mainly uses Redis to implement the cache function.
2. Using
in Nest.js Version:
Library | Version |
---|---|
Nest.js | V8.1.2 |
project is based on the Nest.js 8.x
version, which is different from the Nest.js 9.x
version. The following article specifically sorts out the differences between the two versions. Instructions and how to upgrade from V8
to V9
will not be discussed here.
First, we connect Redis in the Nest.js project. The parameters required to connect Redis:
REDIS_HOST:Redis 域名 REDIS_PORT:Redis 端口号 REDIS_DB: Redis 数据库 REDIS_PASSPORT:Redis 设置的密码
Write the parameters into .env
and .env. prod
In the configuration file:
Use the method officially recommended by Nest, which only requires 3 simple steps:
1. Introduce dependency files
npm install cache-manager --save npm install cache-manager-redis-store --save npm install @types/cache-manager -D
Nest
Provides a unified API for various cache storage. The built-in data storage is in-memory, but you can also use cache-manager
to use other solutions. For example, use Redis
for caching.
To enable caching, import ConfigModule
, and call register()
or registerAsync()
to pass in the response configuration parameters.
2. Create module file src/db/redis-cache.module.ts
, implemented as follows:
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
Method uses Redis Store configuration to communicate -
store
Attribute valueredisStore
, indicating 'cache-manager-redis-store' library -
isGlobal
property is set totrue
to declare it as a global module, when we importRedisCacheModule
inAppModule
, other modules can be used directly without importing again. - Since the Redis information is written in the configuration file, the
registerAsync()
method is used to process asynchronous data. If it is static data, you can Useregister
3, create a new redis-cache.service.ts
file, and implement cache read and write
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); } }
connections in the service Come down and import RedisCacheModule
in app.module.ts
.
Adjust token issuance and verification process
We use redis to implement token expiration processing, automatic token renewal, and unique user login.
- Expiration processing: put user information and token into redis, and set the expiration time
- Token automatic renewal: the token expiration time is 30 minutes, if within these 30 minutes If there is no operation, log in again. If there is an operation within 30 minutes, the token will be automatically renewed for a new time to prevent disconnection during use.
- Unique login for each user: same account, different computer login, the user who logs in first will be pushed offline by the user who logs in later
Token expiration processing
After logging in At this time, store the token generated by jwt into redis and set the validity period to 30 minutes. The key stored in redis consists of user information, and value is the token 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 }; }
When verifying the token, get the token from redis. If you cannot get the token, the token may have expired.
// jwt.strategy.ts + import { RedisCacheService } from './../core/db/redis-cache.service'; 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('SECRET'), + 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('token 已过期'); + } const existUser = await this.authService.getUser(user); if (!existUser) { throw new UnauthorizedException('token不正确'); } return existUser; } }
User's only login
When a user logs in, each new token issued will overwrite the previous token and determine the token in redis and the request incoming Are the tokens the same? If not, it may be that the user has logged in elsewhere and a token error is displayed.
// 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('token 已过期'); } + if (token != cacheToken) { + throw new UnauthorizedException('token不正确'); + } const existUser = await this.authService.getUser(user); if (!existUser) { throw new UnauthorizedException('token不正确'); } return existUser; }
Token automatic renewal
There are many implementation solutions, you can generate access_token
(jwt valid for 30 minutes) and through background jwt refresh_token
, refresh_token
has a longer validity period than access_token
. The client caches these two tokens. When access_token
expires, the client carries again. refresh_token
Get the new access_token
. This solution requires the cooperation of the developer of the interface call.
I will mainly introduce here, the automatic renewal of token implemented by pure backend
Implementation process:
- ①: When jwt generates a token, the validity period is set to No expiration
- ②: Set the validity period to 30 minutes when redis caches the token
- ③: When the user carries the token request, if the key exists and the value is the same, the validity period is reset to 30 minutes
Set the token generated by jwt so that it does not expire. This part of the code is in the auth.module.ts
file. If you don’t understand, you can read the article Nest.js Practical Series. Part 2 - Implement registration, scan code login, jwt authentication
// auth.module.ts const jwtModule = JwtModule.registerAsync({ inject: [ConfigService], useFactory: async (configService: ConfigService) => { return { secret: configService.get('SECRET', 'test123456'), - signOptions: { expiresIn: '4h' }, // 取消有效期设置 }; }, });
and then reset the expiration time after the token authentication is passed, because the cache-manager
used has not been updated directly The validity period method is implemented by resetting:
// 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('token 已过期'); } if (token != cacheToken) { throw new UnauthorizedException('token不正确'); } const existUser = await this.authService.getUser(user); if (!existUser) { throw new UnauthorizedException('token不正确'); } + this.redisCacheService.cacheSet( + `${user.id}&${user.username}&${user.role}`, + token, + 1800, + ); return existUser; }
At this point, the token expiration processing, token automatic renewal, and user only login are completed in Nest. It is easier to remove the token when logging out. Here are the codes one by one.
In addition to using the officially recommended method in Nest, you can also use nestjs-redis
to implement it. If you want to save the token, you want to save the hash
structure. , when using cache-manager-redis-store
, you will find that there is no hash
value storage and retrieval method (it takes some effort to find out).
Note: If you use
nest-redis
to implement redis caching, an error will be reported under Nest.js 8 version. Friends can use@chenjm/nestjs-redis
instead, or refer to the solution on the issue: Nest 8 redis bug.
Summary
Source code address: https://github.com/koala-coding/nest-blog
More programming related For knowledge, please visit: programming teaching! !
The above is the detailed content of How to use Redis in Node.js? It turns out it's that simple!. For more information, please follow other related articles on the PHP Chinese website!

JavaScript core data types are consistent in browsers and Node.js, but are handled differently from the extra types. 1) The global object is window in the browser and global in Node.js. 2) Node.js' unique Buffer object, used to process binary data. 3) There are also differences in performance and time processing, and the code needs to be adjusted according to the environment.

JavaScriptusestwotypesofcomments:single-line(//)andmulti-line(//).1)Use//forquicknotesorsingle-lineexplanations.2)Use//forlongerexplanationsorcommentingoutblocksofcode.Commentsshouldexplainthe'why',notthe'what',andbeplacedabovetherelevantcodeforclari

The main difference between Python and JavaScript is the type system and application scenarios. 1. Python uses dynamic types, suitable for scientific computing and data analysis. 2. JavaScript adopts weak types and is widely used in front-end and full-stack development. The two have their own advantages in asynchronous programming and performance optimization, and should be decided according to project requirements when choosing.

Whether to choose Python or JavaScript depends on the project type: 1) Choose Python for data science and automation tasks; 2) Choose JavaScript for front-end and full-stack development. Python is favored for its powerful library in data processing and automation, while JavaScript is indispensable for its advantages in web interaction and full-stack development.

Python and JavaScript each have their own advantages, and the choice depends on project needs and personal preferences. 1. Python is easy to learn, with concise syntax, suitable for data science and back-end development, but has a slow execution speed. 2. JavaScript is everywhere in front-end development and has strong asynchronous programming capabilities. Node.js makes it suitable for full-stack development, but the syntax may be complex and error-prone.

JavaScriptisnotbuiltonCorC ;it'saninterpretedlanguagethatrunsonenginesoftenwritteninC .1)JavaScriptwasdesignedasalightweight,interpretedlanguageforwebbrowsers.2)EnginesevolvedfromsimpleinterpreterstoJITcompilers,typicallyinC ,improvingperformance.

JavaScript can be used for front-end and back-end development. The front-end enhances the user experience through DOM operations, and the back-end handles server tasks through Node.js. 1. Front-end example: Change the content of the web page text. 2. Backend example: Create a Node.js server.

Choosing Python or JavaScript should be based on career development, learning curve and ecosystem: 1) Career development: Python is suitable for data science and back-end development, while JavaScript is suitable for front-end and full-stack development. 2) Learning curve: Python syntax is concise and suitable for beginners; JavaScript syntax is flexible. 3) Ecosystem: Python has rich scientific computing libraries, and JavaScript has a powerful front-end framework.


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

mPDF
mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),

SublimeText3 Chinese version
Chinese version, very easy to use

WebStorm Mac version
Useful JavaScript development tools

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver Mac version
Visual web development tools
