美文网首页基础前端
在 NodeJs 中使用 Redis

在 NodeJs 中使用 Redis

作者: CondorHero | 来源:发表于2020-10-22 19:07 被阅读0次

前言:我下一步要写的一篇文章是 Antd@4 table 代校验逻辑的编辑输入框 (现在我想法变了,没意思不写了),所以后台的数据就不能是死的了,必须是活的,也就是说要和数据库交互,之前用过 MySqlmongDB,但是这次不用这两来模拟数据。久闻 Redis 的大名,正好来学习下。

redis.org

演示环境是在 MAC 下:

一、配置环境

安装 Redis,可以选择官网,但是 MAC 有非常好用的包管理工具 brew,当然是它来安装了,只需要一行命令:

brew install redis

OK,安装完成接下来当然是得启动了,也是只需要一句命令 redis-server

➜  redis_study git:(master) ✗ redis-server
25033:C 20 Sep 2020 18:43:52.244 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
25033:C 20 Sep 2020 18:43:52.244 # Redis version=6.0.5, bits=64, commit=00000000, modified=0, pid=25033, just started
25033:C 20 Sep 2020 18:43:52.244 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
                _._                                                  
           _.-``__ ''-._                                             
      _.-``    `.  `_.  ''-._           Redis 6.0.5 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._                                   
 (    '      ,       .-`  | `,    )     Running in standalone mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
 |    `-._   `._    /     _.-'    |     PID: 25033
  `-._    `-._  `-./  _.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |           http://redis.io        
  `-._    `-._`-.__.-'_.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |                                  
  `-._    `-._`-.__.-'_.-'    _.-'                                   
      `-._    `-.__.-'    _.-'                                       
          `-._        _.-'                                           
              `-.__.-'                                               

25033:M 20 Sep 2020 18:43:52.258 # Server initialized
25033:M 20 Sep 2020 18:43:52.259 * Loading RDB produced by version 6.0.5
25033:M 20 Sep 2020 18:43:52.259 * RDB age 11 seconds
25033:M 20 Sep 2020 18:43:52.259 * RDB memory usage when created 0.97 Mb
25033:M 20 Sep 2020 18:43:52.259 * DB loaded from disk: 0.001 seconds
25033:M 20 Sep 2020 18:43:52.259 * Ready to accept connections

启动完成后等待连接,我们先不通过程序来连接,先通过命令行来连接进行学习,输入 redis-cli 进入交互命令行环境:

➜  redis_study git:(master) ✗ redis-cli   
127.0.0.1:6379> 

OK ,顺利进入,控制台显示主机为: 127.0.0.1,端口号为: 6379,默认进入第一个数据库,且不会显示这个数据库的名字。

现在往数据库里面插入一条数据,然后读取出来。

127.0.0.1:6379> set name CondorHero
OK
127.0.0.1:6379> get name
"CondorHero"

这就简简单单的入门了,接下来学基本功能:「增、删、查、改」。

二、 Redis 的基本知识

Redis (REmote Dictionary Server(Redis) 是一个由 Salvatore Sanfilippo 写的 key-value 存储系统。

key-value 存储系统 这句话就是 redis 的精髓,使用上我感觉 Redis 就像是 mongDB 的精简版。

Redis 数据库的数量是固定的,并在配置文件中设置。默认情况下,有 16 个数据库,不要担心数据库不够用的,因为 Redis 基本都是做缓存,不存储大量数据所以完全够用的,另外每个数据库都用数字(而不是名称)标识。

可以使用命令来获取数据库的数量:

127.0.0.1:6379> CONFIG GET DATABASES
1) "databases"
2) "16"

不过感觉坑爹的地方在于 Redis 不支持自定义数据库的名字,每个数据库都以编号命名。开发者则需要自己记录存储的数据与数据库的对应关系,数据库名字没有语意化,不过人家本来就是 NOSQL ,我们也不需要去记住数据库名字。另外 Redis 也不支持为每个数据库设置不同的访问密码。就感觉挺方便。

Redis 是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
它通常被称为数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Hash), 列表(list), 集合(sets) 和 有序集合(sorted sets)等类型。

Redis 的命令很多,不过不需要掌握那么多,用到的时候查文档就行了,Redis 官网做的还是很不错的,所以起来很方便:https://redis.io/commands

不过需要掌握以下常用的:

启动
redis-server
or
redis-server --port 6380

停止
redis-cli SHUTDOWN
or
kill RedisPID

连接 Redis
redis-cli
or
redis-cli -h 127.0.0.1 -p 6379

测试客户端与 Redis 连接是否正常,正常会收到回复 PONG
redis-cli PING


所有数据库 key 的情况:
INFO Keyspace

切换数据库:
SELECT 15

查看数据库大小:
DBSIZE

查看当前数据库所有的 key 值 :
KEYS * 

清空所有数据库的数据:
FLUSHALL 

清空当前数据库的数据:
FLUSHDB 

是否存在 key :存在返回 1 不存在返回 0
EXISTS name 

十秒之后 name 这个 key 就没了 (过期):
EXPIRE name 10 

查看剩余过期时间(time to live):
ttl name 

移动 name 这个 key 到 1数据库
MOVE name 1 

设置 name 这个 key 的值为 CondorHero:
SET name CondorHero

获取 name 这个 key 的值:
GET name

MSET 批量设置
MGET 批量获取

删除 name 这个 key:
DEL name

如果获取不到 age 的值,就设置age=20并返回,如果能获取到 age 的值,直接返回 age 的值
GETSET age 20

查看当前key的类型
type name 

获取当前 key 的值之后,在其末尾增加 end:
APPEND name "end" 

获取当前 key 的长度:
STRLEN name 

获取指定范围 key 的值:
GETRANGE key 0 0 // 获取第一个
GETRANGE key 0 -1 //获取全部

更改 key 的值:
SETRANGE key offset value


set width expire
SETEX age 10
set not if exist
SETNX key value

批量操作,有 Promise.all 的表现:
MSETNX


readCount
SET readCount 10
INCR readCount //++ 11
DECR readCount  //-- 10
INCRBY readCount 10 //+= 10 20
DECRBY readCount 10 //-= 10 10

还有个很有意思的事情,默认端口号 6379 的来历:

Redis 作者女儿的名字,对应九宫格输入法的数字。可以去看看作者怎么说的 👉 Redis 为什么要用 6379 作为默认端口?

还有一个问题,Redis为什么是单线程,而6.0要引入多线程? 我想会 NodeJs 的同学看下这个博客Redis为什么是单线程,而6.0要引入多线程就很容易理解。

重头戏来了。

三、NodeJs 连接 Redis

第一步: 安装依赖

npm i -D redis

第二步:简单写一个例子

const redis = require("redis");
// 连接 Redis
const client = redis.createClient({ host: "127.0.0.1", port: 6379 });

// 使用事件发射器,检测错误
client.on("error", function (error) {
    console.error(error);
});

// console 来验证 Redis 的 API 是异步
console.log("🦋🦋🦋🦋");
// 存储一个 key value
client.set("name", "Condor Hero", redis.print);
console.log("🐥🐥🐥🐥");
// 读取 name 这个 key 的值
client.get("name", redis.print);
console.log("🐝🐝🐝🐝");
// 退出 Redis
client.quit();
console.log("🦄🦄🦄🦄");
/* 
    redis.print 就是一个函数,用来打印出,API执行完之后的结果
    既然redis.print是个函数,那么我们完全可以把 redis.print 替换为我们熟悉的console.log,
    甚至自定义结合 chalk 自定义一个函数放进去
*/

第三步:调试

node app.js
🦋🦋🦋🦋
🐥🐥🐥🐥
🐝🐝🐝🐝
🦄🦄🦄🦄
Reply: OK
Reply: Condor Hero

不出所料,API 都是异步的所以我们编程的时候要注意⚠️。

四、项目中简单封装使用

演示项目目录如下:

├── app.js              # 程序入口
├── config              # 配置文件,例如账号端口号等
│   └── index.js
├── db
│   ├── index.js        # 导出不同数据库的 API
│   ├── mysql
│   │   └── index.js    # 对 Mysql 的 API 进行封装
│   └── redis
│       └── index.js    # 对 Redis 的 API 进行封装
├── package-lock.json
└── package.json        # 依赖文件

config/index.js 注意变量命名格式:

// Redis 配置
const REDIS_CONFIG = {
    host: "127.0.0.1",
    port: 6379
};

// mysql 配置
const MYSQL_CONFIG = {
    host: "127.0.0.1",
    port: 6379
};

module.exports = {
    REDIS_CONFIG,
    MYSQL_CONFIG
};

db/redis/index.js 借助数据库的 API,进行封装满足项目需求:

const redis = require("redis");
const chalk = require("chalk");
const { REDIS_CONFIG } = require("../../config");
const { host, port } = REDIS_CONFIG;
const client = redis.createClient({ host, port });

client.on("error", function (error) {
    console.error(chalk.red(error));
});

/* Redis API 为异步,使用 Promise 封装 */
function set (key, value) {
    return new Promise((resolve, reject) => {
        /* Only strings, dates and buffers are accepted */   
        /* set 只能存储字符串、日期、buffers,所以如果要存储非字符串要转成字符串 */
        if (typeof value === "object") {
            JSON.stringify(value);
        } else if (value === undefined) {
            reject("value 不能为 undefined");
            return;
        };

        client.set(key, value, (err, replay) => {
            err && reject(err);
            resolve(replay);
        });
    });
};

function get (key) {
    return new Promise((resolve, reject) => {
        client.get(key, (err, val) => {
            err && reject(err);
            
            /* 利用 JSON.parse(string) 报错返回正确的数据格式 */
            try {
                resolve(JSON.parse(val));
            } catch (error) {
                resolve(val);
            }
        });
    });
};

module.exports = {
    get,
    set
};

db/index.js 汇总导出:

const redis = require("./redis");
const mysql = require("./mysql");

module.exports = {
    redis,
    mysql
};

我们在 app.js 文件里面随便使用下:

const { redis } = require("./db");
const chalk = require("chalk");

redis.set("name", "Condor Hero").then(res => {
    redis.get("name").then(val => {
        console.log(chalk.green(val));
        process.exit(1);
    });
});

启动的运行结果为:

➜  redis_study git:(master) ✗ node app.js
Condor Hero

OK,现在成功的掌握了 Redis 技术,然并没啥鸟用。现在工作连 Vue 都用不到,更 TMD 的没机会去写 NodeJs。我心心念念不忘的移动端小程序啥的一点都接触不到,老是用 React 搞 PC 后台,逻辑写的我都快要吐了。

入职以来,建议了八百次了,双框架开发,奈何人微言轻,意见不被采纳,郁闷😒。

最近唯一比较开心的就是能看懂下面这张 Chrome network 面板的 timing 资源加载图,学了不少 Chrome 开发工具的知识,你也来猜猜看下图爆错的原因呗 🧐:


完。

当前时间 Thursday, October 22, 2020 19:00:41 写于北京公司

相关文章

网友评论

    本文标题:在 NodeJs 中使用 Redis

    本文链接:https://www.haomeiwen.com/subject/cxkuyktx.html