服务粉丝

我们一直在努力
当前位置:首页 > 财经 >

快速入门 Redis 并在 Node.js 里操作它

日期: 来源:神光的编程秘籍收集编辑:神说要有光zxg

提到数据库,大家可能会想到 mysql,它是通过表和字段来存储信息的,表和表之间通过 id 关联,叫做关系型数据库。

它提供了 sql 语言,可以通过这种语言来描述对数据的增删改查。

mysql 是通过硬盘来存储信息的,并且还要解析并执行 sql 语句,这些决定了它会成为性能瓶颈。

也就是说服务端执行计算会很快,但是等待数据库查询结果就很慢了。

那怎么办呢?

计算机领域最经常考虑到的性能优化手段就是缓存了。

能不能把结果缓存在内存中,下次只查内存就好了呢?

内存和硬盘的速度差距还是很大的:

所以做后端服务的时候,我们不会只用 mysql,一般会结合内存数据库来做缓存,最常用的是 redis。

因为需求就是缓存不同类型的数据,所以 redis 的设计是 key、value 的键值对的形式。

并且值的类型有很多:字符串(string)、列表(list)、集合(set)、有序集合(sorted set)、哈希表(hash)、地理信息(geospatial)、位图(bitmap)等。

我们分别来试一下。

redis 是分为服务端和客户端的,它提供了一个 redis-cli 的命令行客户端。

首先我们把 redis 服务跑起来。

通过 docker 的形式来跑:

下载一个 docker desktop 桌面端工具:

左边分别是镜像和镜像跑起来后的容器。

在搜索框搜索 redis,点击 run,把 redis 官方镜像下载并跑起来。

它会让你填一些容器的信息:

名字没啥好说的。

端口映射就是把主机的 6379 端口映射到容器内的 6379 端口,这样就能直接通过本机端口访问容器内的服务了。

volume 是数据卷,也就是挂载本地目录到容器的一个目录。

为什么要挂载数据卷呢?

因为镜像是不可修改的,每次运行都是全新的,但如果每次跑 redis 镜像,之前的数据都清空了可咋办?

所以要把本机的一个目录挂载上去,数据保存在本机。

跑起来之后是这样的:

容器内打印的日志说明 redis 服务跑起来了。

files 里可以看到所有的容器内的文件:

看到这个 mounted 的标志了没?

就代表这个目录是挂载的本地的一个目录。

我们在本地目录添加一个文件。

在容器内的 data 目录就能访问到这个文件了:

同样,在容器内修改了 data 目录,那本机目录下也会修改。

redis 服务跑起来之后,我们用 redis-cli 操作下。

在 terminal 输入 redis-cli,进入交互模式:

我们在这里做下 string 相关的操作:

文档里的命令有这么几个:

set、get 都挺简单:

incr 是用于递增的:

平时我们用的阅读量、点赞量等都是通过这个来计数的。

当我存了几个 key 后,可以通过 keys 来查询有哪些 key:

keys 后加一个模式串来过滤,常用的是 '*' 来查询所有 key。

然后再来看看 list。

这里我们切换成 GUI 工具吧,那个更直观一些。

这个就像 git 有人喜欢用命令行,有人喜欢用 GUI 工具一样。只是习惯问题,都可以。

我用的是 medis,一个 mac 上的开源 redis GUI 工具。

输入 ip 和端口之后点击连接:

就可以可视化看到所有的 key 和值:

同样也可以执行命令:

(不想装 GUI 工具的同学直接用 redis-cli 也是一样的,没啥区别)

然后我们继续看 list 类型的数据结构:

文档中有这么几个命令:

我们试一下:

lpush 是 left push 的意思,执行后会从左到右添加到列表中:

rpush 是 right push 的意思,执行后会从右往左添加到列表中:

(在 GUI 里要全选执行)

lpop 和 rpop 自然是从左边和从右边删除数据。

如果想查看数据呢?

在 GUI 里直接点开看就行,但在命令行里呢?

有同学说,不就是 get 么?

是不行的,get 只适用于 string 类型的数据,list 类型的数据要用 lrange。

输入一段 range,结尾下标为 -1 代表到最后。lrange list1 0 -1 就是查询 list1 的全部数据。

接下来我们再来看看 set:

set 的特点是无序并且元素不重复。

当我添加重复数据的时候:

只保留去重后的数据:

可以通过 sismember 判断是否是集合中的元素:

set 只能去重、判断包含,不能对元素排序。

如果排序、去重的需求,比如排行榜,可以用 sorted set,也就是 zset,:

它每个元素是有一个分数的:

image.png

会按照分数来排序:

通过 zrange 命令取数据,比如取排名前三的数据:

接下来是 hash:

和我们用的 map 一样,比较容易理解:

再就是 geo 的数据结构,就是经纬度信息,根据距离计算周围的人用的:

平时我们查找周围的人、周围的 xxx 都可以通过 redis 的 geospatial 数据结构实现。

redis 的数据结构就先介绍到这里。

是不是感觉还挺简单的。

确实,redis 学习成本挺低的,过一遍就会了。

不过一般 redis 的 key 我们会设置过期时间,通过 expire 命令:

比如我设置 dong2 的 key 为 3 秒过期:

3s 后就查不到了:

想查剩余过期时间使用 ttl:

一些有时效的数据可以设置个过期时间。

会了在命令行中操作 redis,重点还是要在代码里操作。

这就需要用 redis 的 node 的客户端了。

官方提供了 redis 这个 npm 包,我们安装一下:

npm install redis

然后在代码里连接 redis 服务,并执行命令:

import { createClient } from 'redis';

const client = createClient({
    socket: {
        host: 'localhost',
        port: 6379
    }
});

client.on('error', err => console.log('Redis Client Error', err));

await client.connect();

const value = await client.keys('*');

console.log(value);

await client.disconnect();

执行结果如下:

这里我能直接跑 es module 并且可以写顶层 await 是因为我在 package.json 里配置了 type: module。

我们再执行其他命令试试,比如 hset 创建一个 hash 表:

await client.hSet('guangguang1', '111', 'value111');
await client.hSet('guangguang1', '222', 'value222');
await client.hSet('guangguang1', '333', 'value333');

执行以后是这样的:

和我们在命令行客户端里操作一样。

这样我们就完成了 node 里操作 redis 的功能。

一般我们开发 node 应用会使用 nest 来写,那 nest 里怎么操作 redis 呢?

其实也是一样的:

执行 nest new nest-redis 创建一个 nest 项目:

它的 AppModule 是这样的:

我们给它添加一个 provider,返回 redis 的 client 实例。

当然,要先 npm install redis 安装 npm 包。

然后添加一个自定义的 provider:

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { createClient } from 'redis';

@Module({
  imports: [],
  controllers: [AppController],
  providers: [
    AppService,
    {
      provide: 'REDIS_CLIENT',
      async useFactory() {
        const client = createClient({
            socket: {
                host: 'localhost',
                port: 6379
            }
        });
        await client.connect();
        return client;
      }
    }
  ],
})
export class AppModule {}

provider 通过工厂方法创建,token 为 REDIS_CLIENT。

然后注入到 service 里用就好了:

import { Inject, Injectable } from '@nestjs/common';
import { RedisClientType } from 'redis';

@Injectable()
export class AppService {

  constructor(@Inject('REDIS_CLIENT') private redisClient: RedisClientType) {}

  async getHello() {
    const value = await this.redisClient.keys('*');
    console.log(value);

    return 'Hello World!';
  }
}

这样就能在 nest 里操作 redis 了:

这就是 redis 的使用和在 nodejs 里操作 redis 的方式。

回到最开始的问题,我们完全可以查出数据来之后放到 redis 中缓存,下次如果 redis 有数据就直接用,没有的话就查数据库然后更新 redis 缓存。

这是 redis 的第一种用途,作为数据库的缓存。

第二种用途就是直接作为存储数据的地方了,因为 redis 本身是会做持久化的,也可以把数据直接保存在 redis 里,不存到 mysql。

当然,因为 redis 在内存存储数据,这样成本还是比较高的,需要经常扩容。

总结

因为 mysql 存在硬盘,并且会执行 sql 的解析,会成为系统的性能瓶颈,所以我们要做一些优化。

常见的就是在内存中缓存数据,使用 redis 这种内存数据库。

它是 key、value 的格式存储的,value 有很多种类型,比如 string、list、set、sorted set(zset)、hash、geopitial 等。

灵活运用这些数据结构,可以完成各种需求,比如排行榜用 zset、阅读数点赞数用 string、附近的人用 geopitial 等。

而且这些 key 都可以设置过期时间,可以完成一些时效性相关的业务。

通过 redis 的 npm 包就可以轻松的连接和操作 redis 了,如果在 nest 里,可以封装一个 provider,在里面使用 redis 的 npm 包创建连接。

redis 几乎和 mysql 一样是后端系统的必用中间件了,它除了用来做数据库的缓存外,还可以直接作为数据存储的地方。

学会灵活使用 redis,是后端开发很重要的一步。

相关阅读

  • 理解AutoGPT原理

  • 看过上次文章的朋友应该学会抢答了:对,就是提示词。那么具体是怎么做的呢?首先启动时你需要设置三个项目:你的机器人名字、你设定给机器人的角色、你要完成的目标。根据你的设定
  • 大力真的有奇迹

  • 在之前那篇颇受欢迎的卖惨小品【今天被OpenAI爆了】里,我讲述了被GPT embedding震撼的故事。但故事的最后,我们并没有采用openai的embedding接口,因为那样确实成本和产品稳定性
  • NLP重铸篇之LLM系列(Codex)

  • codex论文标题:Evaluating Large Language Models Trained on Code论文链接:https://arxiv.org/pdf/2107.03374.pdf论文数据地址:https://www.github.com/openai/human-evalGPT
  • 如何看待一季度经济数据及后续趋势︱重阳问答

  • 【欢迎收听音频版】Q:请问重阳投资,如何看待一季度经济数据及后续趋势?A:一季度宏观经济数据出炉,我们的观点可以用总量有惊喜,结构在分化,后续有期待来概括。一季度经济数据最大的
  • 【广发言·特刊】世界读书日专题(下期)

  • 导读:莎士比亚说过:“生活里没有书籍,就好像没有阳光;智慧里没有书籍,就好像鸟儿没有翅膀。”关于读书的意义,见仁见智;但大家普遍认可读书是一个学习输入的过程。一年前,我们开设了
  • 10种经典的螺栓防松设计

  • 机械设备中螺栓连接一旦松懈,会引起螺栓脱落导致重大安全隐患,或螺栓松弛预紧力下降导致螺栓连接疲劳寿命大大缩短。因此在设计中要选用适当的防松措施保证螺栓在实际使用中不
  • 数据指标、A/B实验如何驱动业务增长?

  • 导读:上一篇《如何成为一名优秀的数据架构师?》我们阐述了四大体系之数据架构体系,解释了云原生大数据实践、国产数据库创新变革、湖仓一体落地实践、OLAP 发展趋势四个论坛的

热门文章

  • “复活”半年后 京东拍拍二手杀入公益事业

  • 京东拍拍二手“复活”半年后,杀入公益事业,试图让企业捐的赠品、家庭闲置品变成实实在在的“爱心”。 把“闲置品”变爱心 6月12日,“益心一益·守护梦想每一步”2018年四
  • 美国对华2000亿关税清单,到底影响有多大?

  • 1 今天A股大跌,上证最大跌幅超过2%。直接导火索是美国证实计划对华2000亿美元产品加征25%关税。 听起来,2000亿美元数目巨大,我们来算笔账。 2000亿美元,按现在人民币汇率

最新文章

  • 快速入门 Redis 并在 Node.js 里操作它

  • 提到数据库,大家可能会想到 mysql,它是通过表和字段来存储信息的,表和表之间通过 id 关联,叫做关系型数据库。它提供了 sql 语言,可以通过这种语言来描述对数据的增删改查。mysql
  • 理解AutoGPT原理

  • 看过上次文章的朋友应该学会抢答了:对,就是提示词。那么具体是怎么做的呢?首先启动时你需要设置三个项目:你的机器人名字、你设定给机器人的角色、你要完成的目标。根据你的设定
  • 大力真的有奇迹

  • 在之前那篇颇受欢迎的卖惨小品【今天被OpenAI爆了】里,我讲述了被GPT embedding震撼的故事。但故事的最后,我们并没有采用openai的embedding接口,因为那样确实成本和产品稳定性
  • 元语智能招募大模型方向NLP算法实习生(2名)

  • 杭州元语智能招募大模型方向NLP算法实习生(2名) 元语智能:作为大模型研发和应用公司,致力于通用大模型的行业化和应用化。先后发布了百亿类ChatGPT模型ChatYuan,近十亿参数ChatYu
  • NLP重铸篇之LLM系列(Codex)

  • codex论文标题:Evaluating Large Language Models Trained on Code论文链接:https://arxiv.org/pdf/2107.03374.pdf论文数据地址:https://www.github.com/openai/human-evalGPT
  • 【第2923期】选择无聊的技术

  • 前言“快乐来自于推出产品”,喜欢这句。今日前端早读课文章由 @Chun-Fu Chao 翻译分享。前端早读课:与你分享“我”的视界。正文从这开始~~嘿我是 Dan McKinley。这是我在坑里的