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

演示环境是在 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 写于北京公司
网友评论