# 内存缓存redis

# 一、redis介绍

Redis 是完全开源的,遵守 BSD 协议,是一个高性能的 key-value 数据库。

Redis 与其他 key - value 缓存产品有以下三个特点:

  • Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
  • Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
  • Redis支持数据的备份,即master-slave模式的数据备份。

# redis优势

  • 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
  • 丰富的数据类型 – Redis支持二进制的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
  • 原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
  • 丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。

# redis安装

安装

# 二、redis数据类型

Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。

# String(字符串)

string 是 redis 最基本的类型,你可以理解成与 Memcached 一模一样的类型,一个 key 对应一个 value。

string 类型是二进制安全的。意思是 redis 的 string 可以包含任何数据。比如jpg图片或者序列化的对象。

string 类型是 Redis 最基本的数据类型,string 类型的值最大能存储 512MB。

# Hash(哈希)

Redis hash 是一个键值对集合。Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。

# List(列表)

Redis 列表是简单的字符串双向链表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。应用场景:最新消息排行等功能(比如朋友圈的时间线)和消息队列。

# Set(集合)

Redis 的 Set 是 string 类型的无序集合。集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。集合提供了求交集、并集、差集等操作。应用场景:共同好友、利用唯一性,统计访问网站的所有独立ip、好友推荐时,根据tag求交集,大于某个阈值就可以推荐。

# zset(有序集合)

Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。zset的成员是唯一的,但分数(score)却可以重复。数据插入有序集合时,已经进行天然排序。应用场景:排行榜、带权重的消息队列。

# 三、node操作redis

var redis = require('redis')

// 创建redis客户端
var client = redis.createClient(6379, '127.0.0.1')
client.on('error', (err) => {
    console.log('Error ' + err);
});

// 1、字符串
client.set('color', 'red', redis.print);
client.get('color', (err, value) => {
    if (err) throw err;
    console.log('Got: ' + value)
    client.quit();
})

// 2、哈希表
client.hmset('kitty', {
    'age': '2-year-old',
    'sex': 'male'
}, redis.print);
client.hget('kitty', 'age', (err, value) => {
    if (err) throw err;
    console.log('kitty is ' + value);
});
// 遍历kitty
client.hkeys('kitty', (err, keys) => {
    if (err) throw err;
    keys.forEach((key, i) => {
        console.log(key, i);
    });
    client.quit();
});

// 3、列表
// lpush向链表中添加值
client.lpush('tasks', 'Paint the house red.', redis.print);
client.lpush('tasks', 'Paint the house green.', redis.print);
// lrange获取参数start和end范围内的链表元素, 参数end为-1,表明到链表中最后一个元素。
client.lrange('tasks', 0, -1, (err, items) => {
    if (err) throw err;
    items.forEach((item, i) => {
        console.log(' ' + item);
    });
    client.quit();
});

// 4、集合
// 往集合添加元素
client.sadd('ip', '192.168.3.7', redis.print);
client.sadd('ip', '192.168.3.7', redis.print);
client.sadd('ip', '192.168.3.9', redis.print);
client.smembers('ip', (err, members) => {
    if (err) throw err;
    console.log(members);
    client.quit();
});

// 5、有序集合
// 添加元素,第一个参数是key,后面的是元素的score和元素的值
client.zadd(['db', 0, 'mysql', 1, 'mongo', 2, 'redis'])
client.zrange('db', 0, 2, (err, data) => {
    if (err) throw err;
    console.log(data);
    client.quit();
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

# 四、redis实现排行榜

var redis = require('redis'),
    RDS_PORT = 6379,                //端口号  
    RDS_HOST = '127.0.0.1',         //服务器IP  要连接的A服务器redis  
    //RDS_PWD = '123456',           //密码  
    RDS_OPTS = {},                  //设置项  

    redisClient = redis.createClient(RDS_PORT, RDS_HOST, RDS_OPTS);
// client.auth(RDS_PWD,function(){  
//     console.log('通过认证');  
// });  

redisClient.on('connect', async function () {
    console.log('==Redis== Connect');

    //按照 Score1,Key1,Score2,Key2,Score3,Key3方式初始化的
    var vals = [13, 1, 12, 2, 14, 3, 20, 4]
    console.log("==Jain== 4: vals: " + vals)

    await redisClient.zadd('mysort', vals, function (err, res) {
        console.log("==Jain== 5.1")
        if (err != null) {
            console.log("==Jain== error is: ", err);
        } else {
            console.log(res);
        }
    });

    //无穷大和无穷小的分数区间内,key排名情况
    await redisClient.zrange('mysort', 0, -1, function (err, res) {
        console.log("==Jain== 5.2")
        if (err != null) {
            console.log("==Jain== error is: ", err);
        } else {
            console.log(res);
        }
    });

    //无穷大和无穷小的分数区间内,排名总数
    await redisClient.zcount('mysort', -Infinity, Infinity, function (err, res) {
        console.log("==Jain== 5.3")
        if (err != null) {
            console.log("==Jain== error is: ", err);
        } else {
            console.log(res);
        }
    });

    //无穷大和无穷小的分数区间内,从大到小的排序
    var args1 = ['mysort', '+inf', '-inf'];
    await redisClient.zrevrangebyscore(args1, function (err, res) {
        console.log("==Jain== 6.1")
        if (err != null) {
            console.log("==Jain== error is: ", err);
        } else {
            console.log(res);
        }
    });

    //指定分数区间,指定查询数量,偏移指定位数后的排名
    var max = 25, min = 1, offset = 0, count = 4;
    var args2 = ['mysort', max, min, 'WITHSCORES', 'LIMIT', offset, count];
    await redisClient.zrevrangebyscore(args2, function (err, res) {
        console.log("==Jain== 6.2")
        if (err != null) {
            console.log("==Jain== error is: ", err);
        } else {
            console.log(res);
        }
    });

    //根据key去对应排名,从大到小,排名从0开始所以+1
    var args3 = ['mysort', 4]
    await redisClient.zrevrank(args3, function (err, res) {
        console.log("==Jain== 7.1")
        if (err != null) {
            console.log("==Jain== error is: ", err);
        } else {
            console.log(res);
        }
    });

    return
});

redisClient.on('ready', function (err) {
    console.log('==Redis== Ready');
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
Last Updated: 11/24/2020, 12:34:38 PM