技术咨询、项目合作、广告投放、简历咨询、技术文档下载
点击这里 联系博主
# redis在node中的使用
在编写【日程安排吧】 (opens new window)微信小程序中有使用到 redis 进行缓存,现简单介绍一下在 nodejs 中如何使用 redis,以及如何对 redis 的读取进行简单的封装。
# 环境准备
在 node 中使用 redis 的前提是您的主机装有 redis;其安装方式如下:
- centos 安装 redis
# 安装Redis
sudo yum -y install redis
# 启动redis
sudo systemctl start redis
# 给Redis设置密码,取消注释如下这一行
#requirepass foobared
requirepass 密码
# 重启
sudo systemctl restart redis
# 其他
systemctl start redis.service #启动redis服务器
systemctl stop redis.service #停止redis服务器
systemctl restart redis.service #重新启动redis服务器
systemctl status redis.service #获取redis服务器的运行状态
systemctl enable redis.service #开机启动redis服务器
systemctl disable redis.service #开机禁用redis服务器
- mac 安装 redis
# 安装
brew install redis
# 1. 启动redis
brew services start redis
# 2.关闭redis服务
brew services stop redis
# 3.重启redis服务
brew services restart redis
# redis的配合文件地址: /usr/local/etc/redis.conf
vim /usr/local/etc/redis.conf
# 修改密码
requirepass 密码
# 重启
brew services restart redis
安装完成 redis 后,您就可以在项目工程下运行如下命令:
npm install redis
# 如果有typescript的同学,可以安装如下依赖
npm install --save-dev @types/redis
# 对 redis 的简单封装
我们先说说简单的使用吧,在 nodejs 中使用 redis 其实是比较简单的,创建一个 client,然后进行读取和写入的操作;
import * as Redis from "redis";
const client = Redis.createClient({
host: "localhost",
port: 6379,
});
//连接错误处理
client.on("error", (err) => {
console.log("redis connect err", err);
});
client.on("connect", () => {
console.info("redis connect success");
});
// 一个简单的数据存储
client.set("travel:i-wants", "{a:1}", function(err, result) {});
client.get("travel:i-wants", function(err, result) {
console.log(result);
});
通过如上的代码我们发现如下几个问题:
- redis npm 版本,读取和存储使用的是回调函数方式; 【解决办法】我们可以转换成 promise 的形式;
- 对数据的存取每次都需要分别处理错误和正常的情况; 【解决办法】统一处理错误和数据封装
- 每次对存取数据需要写一堆 key【解决办法】key 统一提炼为常量
改造之后的代码:
import * as Redis from "redis";
const client = Redis.createClient({
host: "localhost",
port: 6379,
});
//连接错误处理
client.on("error", (err) => {
console.log("redis connect err", err);
});
client.on("connect", () => {
console.info("redis connect success");
});
type RedisHelperBase = {
setData: (key: string, value: any, expire?: number) => Promise<any>;
getData: (key: string) => Promise<any>;
};
// 统一处理promise的正确和错误,使用时 直接这样使用即可const [error,data] = await xxxx(); 摆脱.then .catch
function awaitWrap<T, U = any>(
promise: Promise<T>
): Promise<[U | null, T | null]> {
return promise
.then<[null, T]>((data: T) => [null, data])
.catch<[U, null]>((err) => [err, null]);
}
// 统一封装redis数据的存和取
const redisHelper: RedisHelperBase = {
/**
*
* @param key key
* @param value 值
* @param expire 默认为5分钟
*/
setData: (key, value, expire = 60 * 5) => {
return awaitWrap( // 外层统一处理promise的then和.catch情况
new Promise((resolve, reject) => {
// 我这里存储的数据为string,如果是对象类型则进行转换,其实这里使用typeof value === "object" 判断也不完全正确
client.set(
key,
typeof value === "object" ? JSON.stringify(value) : value,
function (err, result) {
if (err) {
reject(err);
}
// 如果传递过期时间,那么就对指定的key的数据设置过期
if (!isNaN(expire) && expire > 0) {
client.expire(key, expire);
}
resolve(result);
}
);
})
);
},
getData: (key) => {
return awaitWrap( // 外层统一处理promise的then和.catch情况
new Promise((resolve, reject) => {
client.get(key, function (err, result) {
if (err) {
reject(err);
}
if (result) {
try {
// 对数据进行解析,如果是非object的话,就直接返回内容,否则进行数据解析为Object
resolve(JSON.parse(result));
} catch (error) {
resolve(result);
}
} else {
resolve(result);
}
});
})
);
},
};
export { redisHelper };
export default redisHelper;
export * from "./const";
# 在实际业务中使用
上述我们已经简单封装了 redis 的存储,下面简单介绍一下在业务中如何使用:
以【日程安排吧】 (opens new window)小程序中的【想要的功能】查询和删除为例:
// 数据的查询
export async function query(ctx: BaseContext<{ status?: string }>) {
// ...请求的参数
// 先从redis中读取,分为两个参数,第一个参数为是否error,第二个为具体的内容
const [error, data] = await redisHelper.getData(wantRedisKey(status));
// 如果报错或者有没有数据就查询一下数据库
if (error || (!error && !data)) {
const result = await sequelize.transaction(async () => {
return await WantsModel.findAll({
// ...
});
});
responseSuccess(ctx, result);
// 数据同步到redis中
await redisHelper.setData(wantRedisKey(status), result);
} else {
responseSuccess(ctx, data);
}
}
// 数据的删除
export async function deleteItem(
ctx: BaseContext<{ status?: string, id?: string }>
) {
// ...请求的参数
// 先从缓存中读取
const [error, wantList] = await redisHelper.getData(wantRedisKey());
let hasRedisDelete = 0;
// 删除的时候 删除缓存内的数据,提前将缓存内的数据返回给用户
if (!error && wantList && Array.isArray(wantList)) {
const index = wantList.findIndex((ele: any) => ele.id === id);
if (index !== -1) {
responseSuccess(ctx, wantList[index]);
wantList.splice(index, 1);
hasRedisDelete = 1;
// 更新数据
await redisHelper.setData(wantRedisKey(), wantList);
}
}
const result = await sequelize.transaction(async () => {
return await WantsModel.findOne({
where: {
// ....
},
});
});
if (result !== null) {
// 此处也可以设计为软删除,我这边这个直接是硬删除了
result.destroy();
// 没有使用redis的情况,直接返回数据
!hasRedisDelete && responseSuccess(ctx, result);
} else {
responseError(ctx, "数据删除失败,没有查询到此数据");
}
}
至此一个简单的 redis 在 Nodejs 中使用已经介绍完毕,至于 redis 其他的高级用法详情可见 github: redis (opens new window)
- 本文链接: https://mrgaogang.github.io/nodejs/redis%E5%9C%A8node%E4%B8%AD%E7%9A%84%E4%BD%BF%E7%94%A8.html
- 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 许可协议。转载请注明出处!