返回顶部
首页 > 资讯 > 精选 >Node.js中如何使用Redis
  • 802
分享到

Node.js中如何使用Redis

2023-07-04 14:07:03 802人浏览 安东尼
摘要

这篇文章主要介绍了node.js中如何使用Redis的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇node.js中如何使用Redis文章都会有所收获,下面我们一起来看看吧。1. 认识redis对于前端的小伙伴来

这篇文章主要介绍了node.js中如何使用Redis的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇node.js中如何使用Redis文章都会有所收获,下面我们一起来看看吧。

1. 认识redis

对于前端的小伙伴来说,Redis可能相对比较陌生,首先认识一下

Redis是什么

Redis是一个开源(BSD许可)的,基于内存的数据结构存储系统,它可以用作数据库缓存和消息中间件,是现在最受欢迎的 NoSQL 数据库之一。

其具备如下特性:

  • 速度快

    • 单节点读110000次/s,写81000次/s

    • 基于内存运行,性能高效

    • 用 C 语言实现,离操作系统更近

  • 持久化

    • 数据的更新将异步地保存到硬盘(RDB 和 AOF

  • 多种数据结构

    • 不仅仅支持简单的 key-value 类型数据

    • 还支持:字符串、hash、列表、集合、有序集合

  • 支持多种编程语言等等

Redis 典型使用场景

缓存

缓存可以说是Redis最常用的功能之一了, 合理的缓存不仅可以加快访问的速度,也可以减少后端数据库的压力。

排行系统

利用Redis的列表和有序集合的特点,可以制作排行榜系统,而排行榜系统目前在商城类、新闻类、博客类等等,都是比不可缺的。

计数器应用

计数器的应用基本和排行榜系统一样,都是多数网站的普遍需求,如视频网站的播放计数,电商网站的浏览数等等,但这些数量一般比较庞大,如果存到关系型数据库,对MySQL或者其他关系型数据库的挑战还是很大的,而Redis基本可以说是天然支持计数器应用。

(视频直播)消息弹幕

直播间的在线用户列表,礼物排行榜,弹幕消息等信息,都适合使用Redis中的SortedSet结构进行存储。

例如弹幕消息,可使用ZREVRANGEBYSCORE排序返回,在Redis5.0中,新增了zpopmaxzpopmin命令,更加方便消息处理。

Redis的应用场景远不止这些,Redis对传统磁盘数据库是一个重要的补充,是支持高并发访问的互联网应用必不可少的基础服务之一。

纸上谈兵终觉浅,必须实战一波~

Redis的安装和简单使用,我这里就不一一介绍了,这里贴上我之前写的两篇文章:

  • Redis 安装

  • Redis入门篇-基础使用

可以快速的安装、了解Redis数据类型以及常用的命令。

可视化客户端

windows下使用 RedisClient, 在Mac下可以使用Redis Desktop Manager

下载后直接双击redisclient-win32.x86.2.0.exe文件运行即可

Node.js中如何使用Redis

启动后, 点击server -> add

Node.js中如何使用Redis

连接后就可以看到总体情况了:

Node.js中如何使用Redis

sql型数据不同,redis没有提供新建数据库的操作,因为它自带了16(0-15)个数据库(默认使用0库)。在同一个库中,key是唯一存在的、不允许重复的,它就像一把“密钥”,只能打开一把“”。键值存储的本质就是使用key来标识value,当想要检索value时,必须使用与value对应的key进行查找.

2. 在Nest.js中使用

版本情况:

版本
Nest.jsV8.1.2

项目是基于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个步骤:

引入依赖文件

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

登录后复制

Nest为各种缓存存储提供统一的api,内置的是内存中的数据存储,但是也可使用 cache-manager来使用其他方案, 比如使用Redis来缓存。

为了启用缓存, 导入ConfigModule, 并调用reGISter()或者registerAsync()传入响应的配置参数。

创建module文件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 {}

  • CacheModuleregisterAsync方法采用 Redis Store 配置进行通信

  • store 属性值redisStore ,表示'cache-manager-redis-store' 库

  • isGlobal 属性设置为true 来将其声明为全局模块,当我们将RedisCacheModuleAppModule中导入时, 其他模块就可以直接使用,不需要再次导入

  • 由于Redis 信息写在配置文件中,所以采用registerAsync()方法来处理异步数据,如果是静态数据, 可以使用register

新建redis-cache.service.ts文件, 在service实现缓存的读写

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即可。

调整 token 签发及验证流程

我们借助redis来实现token过期处理、token自动续期、以及用户唯一登录。

  • 过期处理:把用户信息及token放进redis,并设置过期时间

  • token自动续期:token的过期时间为30分钟,如果在这30分钟内没有操作,则重新登录,如果30分钟内有操作,就给token自动续一个新的时间,防止使用时掉线。

  • 户唯一登录:相同的账号,不同电脑登录,先登录的用户会被后登录的挤下线

token 过期处理

在登录时,将Jwt生成的token,存入redis,并设置有效期为30分钟。存入redis的key由用户信息组成, value是token值。

// 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 }; }

在验证token时, 从redis中取token,如果取不到token,可能是token已过期。

// 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;  }}

用户唯一登录

当用户登录时,每次签发的新的token,会覆盖之前的token, 判断redis中的token与请求传入的token是否相同, 不相同时, 可能是其他地方已登录, 提示token错误。

// 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自动续期

实现方案有多种,可以后台jwt生成access_token(jwt有效期30分钟)和refresh_token, refresh_token有效期比access_token有效期长,客户端缓存此两种token, 当access_token过期时, 客户端再携带refresh_token获取新的access_token。 这种方案需要接口调用的开发人员配合。

我这里主要介绍一下,纯后端实现的token自动续期

实现流程:

  • ①:jwt生成token时,有效期设置为用不过期

  • ②:redis 缓存token时设置有效期30分钟

  • ③:用户携带token请求时, 如果key存在,且value相同, 则重新设置有效期为30分钟

设置jwt生成的token, 用不过期, 这部分代码是在auth.module.ts文件中, 不了解的可以看文章 Nest.js 实战系列第二篇-实现注册、扫码登陆、jwt认证

// auth.module.tsconst jwtModule = JwtModule.registerAsync({  inject: [ConfigService],  useFactory: async (configService: ConfigService) => {    return {      secret: configService.get('SECRET', 'test123456'),-     signOptions: { expiresIn: '4h' },  // 取消有效期设置    };  },});

然后再token认证通过后,重新设置过期时间, 因为使用的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('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;  }

在Nest中除了使用官方推荐的这种方式外, 还可以使用nestjs-redis来实现,如果你存token时, 希望存hash结构,使用cache-manager-redis-store时,会发现没有提供hash值存取放方法(需要花点心思去发现)。

注意:如果使用nest-redis来实现redis缓存, 在Nest.js 8 版本下会报错, 小伙伴们可以使用@chenjm/nestjs-redis 来代替, 或者参考 issue上的解决方案:Nest 8 + redis bug。

关于“Node.js中如何使用Redis”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“Node.js中如何使用Redis”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注编程网精选频道。

--结束END--

本文标题: Node.js中如何使用Redis

本文链接: https://lsjlt.com/news/345427.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Node.js中如何使用Redis
    这篇文章主要介绍了Node.js中如何使用Redis的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Node.js中如何使用Redis文章都会有所收获,下面我们一起来看看吧。1. 认识redis对于前端的小伙伴来...
    99+
    2023-07-04
  • Node.js中如何使用console
    本篇内容介绍了“Node.js中如何使用console”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!在这篇...
    99+
    2024-04-02
  • Node.js中stream如何使用
    Node.js中stream如何使用,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。使用流的好处举一个读取文件的例子:使用fs.readFi...
    99+
    2024-04-02
  • node.js如何使用redis数据库缓存数据
    这篇文章将为大家详细讲解有关node.js如何使用redis数据库缓存数据,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一、运行redisRedis服务器默认使用6379...
    99+
    2024-04-02
  • Node.js中如何使用RESTful API
    本篇文章为大家展示了Node.js中如何使用RESTful API,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。Node.js RESTful API现在介绍Nod...
    99+
    2024-04-02
  • Node.js中如何使用Puppeteer库
    这篇文章主要讲解了“Node.js中如何使用Puppeteer库”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Node.js中如何使用Puppeteer库”...
    99+
    2024-04-02
  • redis中zset如何使用
    这篇文章将为大家详细讲解有关redis中zset如何使用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。Redis中zset是set的一个升级版本,他在set的基础上增加了...
    99+
    2024-04-02
  • Bump中如何使用Redis
    这篇文章将为大家详细讲解有关Bump中如何使用Redis,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。  Bump的Redis怎么用  1.将Redis用作...
    99+
    2024-04-02
  • redis中如何使用scan
    这篇文章主要为大家展示了“redis中如何使用scan”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“redis中如何使用scan”这篇文章吧。 ...
    99+
    2024-04-02
  • ThinkPHP5中如何使用redis
    目录配置redis使用string(字符串)Hash(哈希)List(列表)Set(集合)zset(有序集合)总结前提:因为本文主要围绕着在thinkPHP5中使用redis的,所以...
    99+
    2023-05-14
    ThinkPHP5使用redis ThinkPHP5 redis
  • springboot中如何使用redis
    这篇文章将为大家详细讲解有关springboot中如何使用redis,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。正文很多时候,我们会在springboot中配置redis,但是就那么几个配置就配好了,没...
    99+
    2023-05-30
    springboot redis
  • Node.js中如何使用DNS模块
    Node.js中如何使用DNS模块,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。1. DNS在Node.js中,提供DNS模块,以实现域名...
    99+
    2024-04-02
  • Node.js 中ECDSA 签名如何使用
    今天就跟大家聊聊有关Node.js 中ECDSA 签名如何使用,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。坑 0x00:签名输出格式在排...
    99+
    2024-04-02
  • Node.js 中domain模块如何使用
    这篇文章给大家介绍Node.js 中domain模块如何使用,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。异步异常处理异步异常的特点由于node的回调异步特性,无法通过try catc...
    99+
    2024-04-02
  • Node.js中如何使用SQLite3和MongoDB
    Node.js中如何使用SQLite3和MongoDB,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。setup.js:初始化数据库var&...
    99+
    2024-04-02
  • Node.js中如何使用Cluster模块
    Node.js中如何使用Cluster模块,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。1.为什么我的应用代码中明明有app....
    99+
    2024-04-02
  • Node.js 中如何使用Express框架
    这期内容当中小编将会给大家带来有关Node.js 中如何使用Express框架,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。Node.js Express 框架Expre...
    99+
    2024-04-02
  • Node.js中如何使用util模块
    本篇文章为大家展示了Node.js中如何使用util模块,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。util.inheritsuitl.inherits(cons...
    99+
    2024-04-02
  • Node.js中stream模块如何使用
    Node.js中stream模块如何使用,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。什么是stream定义流的英文strea...
    99+
    2024-04-02
  • node.js中如何使用url模块
    本篇文章为大家展示了node.js中如何使用url模块,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。引入模块var url = req...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作