认识一下Redis
Redis本质上是一种键值内存数据库,但它在保持键值数据库简单快捷特点的同时,又吸收了部分关系数据库的优点,从而使它的位置处于关系数据库和键值数据库之间。
Redis被很多系统所使用它是由以下几个原因的。
读写非常快。Redis每秒可执行大约110000次的设置(SET)操作,每秒大约可执行81000次的读取/获取(GET)操作,这是非常大的亮点。
可以支持存储多种数据结构。Redis支持存储很多种数据类型,像列表,集合,排序集和散列等等。我们可以使用redis像使用内存一样,很方便的用来存在各类数据。
操作具有原子性。所有Redis操作都是原子操作,这确保如果两个客户端并发访问,Redis服务器能接收更新的值。
丰富的特性。redis能干很多事,但是我们这里只介绍缓存,它还可以用来做消息中间件用来发布订阅消息,或者将其使用在保持用户状态这类地方。
从它的优点也能猜出用来干什么了。像底层的数据库要具备高精准的要求,则注定它的效率会差一点,所以当请求很大时,一般不会直接将请求进入到底层数据库去,而是先通过高效的redis,从它的缓存中去看看有没有请求想要的结果,如果没有再去底层数据库里操作,所以redis最普遍的作用就是帮数据库来“分忧”。
安装
百度搜索一下或者参考http://www.runoob.com/note/36178
使用nodejs操作Redis
我们在github上面搜索一下,可以看到redis
这个库是使用最多的,那么就以此为例介绍一下基本的使用。
redisTool.js
const redis = require("redis");
const { promisify } = require("util");
const CLIENT_CONFIG = {
HOST: "127.0.0.1",
PORT: "6379"
};
//创建redis实例
const client = redis.createClient(CLIENT_CONFIG.PORT, CLIENT_CONFIG.HOST);
//获得promise化的get方法
const getAsync = promisify(client.get).bind(client);
//设置指定key的值为value
function setVal(key, value) {
client.set(key, value);
}
//获取指定key的值
function getAsyncVal(key) {
return getAsync(key);
}
//为指定的key设置有效期
function setExpire(key, seconds) {
client.expire(key, seconds);
}
//删除指定key
function deleteKey(key) {
client.del(key);
}
module.exports = {
setVal,
getAsyncVal,
setExpire,
deleteKey
};
下面的列子我们在redis设置了一个key为test
,值为justyeh
的内容,并设置他的有效期为6s。最终的打印结果是:justyeh justyeh justyeh done
const { setVal, getAsyncVal, setExpire } = require("./redisTool");
function test() {
setVal("test", "justyeh");
setExpire("test", 6);
let timer = setInterval(async () => {
let testVal = await getAsyncVal("test");
if (testVal) {
console.log(testVal);
} else {
console.log("done");
clearInterval(timer);
}
}, 2 * 1000);
}
一个真实的使用场景
考虑下面一个场景,后台需要给前台提供一个接口,用以查询指定用户的基本信息,这个接口的请求频率特别高,如果频繁进行数据库查询的话无疑会给后台造成压力,这时我们就可以引入缓存系统,用来快速返回查询结果,并且减少大量的数据库IO请求。
const { setVal, getAsyncVal, deleteKey } = require("./redisTool");
const express = require("express");
const app = express();
//模拟数据库操作
let STU_INFO_DB = [
{
id: 1,
name: "justyeh",
sex: 1,
tip: "info form database"
}
];
app.listen(3000, () => console.log("express app listening on port 3000!"));
//删除用户
app.post("/api/student", (req, res) => {
STU_INFO_DB = STU_INFO_DB.filter(item => item.id != req.body.id);
//删除用户后清除redis中的内容
deleteKey(`stu_cache_${req.body.id}`);
});
//更新用户
app.post("/api/student", (req, res) => {
let index = STU_INFO_DB.findIndex(item => (item.id = req.body.id));
STU_INFO_DB[index].name = req.body.name;
STU_INFO_DB[index].sex = req.body.sex;
//更新缓存内容
setVal(`stu_cache_${req.body.id}`, JSON.stringify(STU_INFO_DB[index]));
});
//查询用户信息
app.get("/api/student/:id", async (req, res) => {
//检查缓存中是否有值
let redisResult = await getAsyncVal(`stu_cache_${req.params.id}`);
if (redisResult) {
redisResult.tip = "info from redis";
redisResult.resultTime = Date.now();
res.json(JSON.parse(redisResult));
} else {
//缓存中没有值,从数据库中取出并存到redis
let dbResult = STU_INFO_DB.find(item => item.id == req.params.id);
if (dbResult) {
dbResult.resultTime = Date.now();
setVal(`stu_cache_${req.params.id}`, JSON.stringify(dbResult));
res.json(dbResult);
} else {
res.json("sorry,not found this student");
}
}
});