JustYeh的前端博客

前端redis入门

2019-08-29

redis

认识一下Redis

Redis本质上是一种键值内存数据库,但它在保持键值数据库简单快捷特点的同时,又吸收了部分关系数据库的优点,从而使它的位置处于关系数据库和键值数据库之间。

Redis被很多系统所使用它是由以下几个原因的。

  1. 读写非常快。Redis每秒可执行大约110000次的设置(SET)操作,每秒大约可执行81000次的读取/获取(GET)操作,这是非常大的亮点。

  2. 可以支持存储多种数据结构。Redis支持存储很多种数据类型,像列表,集合,排序集和散列等等。我们可以使用redis像使用内存一样,很方便的用来存在各类数据。

  3. 操作具有原子性。所有Redis操作都是原子操作,这确保如果两个客户端并发访问,Redis服务器能接收更新的值。

  4. 丰富的特性。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");
        }
    }
});

相关链接

https://redis.io/

https://github.com/NodeRedis/node_redis