redis

redis对象

redis使用五大数据类型(string、hash、list、set、zset)来表示键和值,key类型一般是字符串, 而value类型则是redis对(redisObject)。 redis中每个对象都是
由redisObject结构来表示:

1
2
3
4
5
6
7
typedef struct redisObject{
unsigned type:4; //对象类型(五大数据类型之一)
unsigned encoding:4;
void *ptr; //指向底层数据结构的指针
int refcount;
unsigned lru:22; //最后一次被程序访问的时间
}robj;

redisObject中将数据属性和数据分开; 数据属性包括数据类型, 存储编码方式、淘汰时钟、引用
计数;
1.数据类型:(枚举值[通过 type 命令来获取])

1
2
3
4
5
6
/* Object types */
#define REDIS_STRING 0
#define REDIS_LIST 1
#define REDIS_SET 2
#define REDIS_ZSET 3
#define REDIS_HASH 4

2.存储编码方式,一个数据,可以多种方式存储 
REDIS_SET的数据编码方式: REDIS_ENCODING_HT / REDIS_ENCODING_INTSET
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
        #define REDIS_ENCODING_RAW      0   // raw representation
#define REDIS_ENCODING_INT 1 // encoded as integer
#define REDIS_ENCODING_HT 2 // encoded as hash table
#define REDIS_ENCODING_ZIPMAP 3 // encoded as zipmap
#define REDIS_ENCODING_LINKEDLIST 4 // encoded as regular linked list
#define REDIS_ENCODING_ZIPLIST 5 // encoded as ziplist
#define REDIS_ENCODING_INTSET 6 // encoded as intset
#define REDIS_ENCODING_SKIPLIST 7 // encoded as skiplist
```
3. 数据类型(5种)可对应的编码实现
```c
//redis字符串实现
REDIS_STRING REDIS_ENCODING_INT
REDIS_STRING REDIS_ENCODING_EMBSTR
REDIS_STRING REDIS_ENCODING_RAW
//redis list实现
REDIS_LIST REDIS_ENCODING_ZIPLIST
REDIS_LIST REDIS_ENCODING_LINKEDLIST
//redis hash实现
REDIS_HASH REDIS_ENCODING_ZIPLIST
REDIS_HASH REDIS_ENCODING_HT
//redis set实现
REDIS_SET REDIS_ENCODING_INTSET
REDIS_SET REDIS_ENCODING_HT
//redis zset实现
REDIS_ZSET REDIS_ENCODING_ZIPLIST
REDIS_ZSET REDIS_ENCODING_SKIPLIST
```

### redis字符串对象
```shell
127.0.0.1:6979> set k1 1
OK
127.0.0.1:6979> object encoding k1 //使用long表示整形
"int"
127.0.0.1:6979> set k3 abcdefghijkabcdefjklhlaskdjflsdjfienzfjdlkasfjlkejlkajelafnd
127.0.0.1:6979> object encoding k3
"raw"
127.0.0.1:6979> set k2 giant
OK
127.0.0.1:6979> object encoding k2
"embstr"
- embstr:【嵌入string】,数据嵌入在redisObject对象中;
- raw: redisObject对象中的指针指向raw地址(sds对象);
- 对于浮点数类型也是作为字符串保存的,在需要的时候再将其转换成浮点数类型。

redis列表对象

1. 列表对象的编码是ziplist或linkedlist。 结构如下:
![](/images/post/redis_list_object.png)

2. 如何确定编码方式
    - 列表保存元素个数小于512个
    - 每个元素长度小于64字节
不能满足两个条件时,使用linkedlist;否则ziplist    

redis 哈希对象

哈希对象的键是一个字符串类型,值是一个键值对集合;
1.编码方式:ziplist / hashtable。 结构如下:
![](/images/post/redis_hash_encoding.png)

2.确定编码方式
    - 列表保存元素个数小于512个
    - 每个元素长度小于64字节
不满足两个条件时,使用hashtable,否则ziplist   

redis set对象

集合中的元素是无序的,因此不能通过索引来操作元素;集合中的元素不能有重复
1.编码方式:intset 或者hashtable
    - intset 编码的集合对象使用整数集合作为底层实现,集合对象包含的所有元素都被保存在整数集合中。
    - hashtable 编码的集合对象使用 字典作为底层实现,字典的每个键都是一个字符串对象,这里的每个字符串对象就是一个集合中的元素,而字典的值则全部设置为 null
结构如下:
![](/images/post/redis_set_encoding.png)    
2.确定编码方式
    - 列表保存元素个数小于512个
    - 集合对象中所有元素都是整数
不满足两个条件时,使用hashtable;否则intset

redis zsort对象

1.编码方式:ziplist 或者 skiplist 
ziplist编码方式结构如下:
![](/images/post/redis_zsort_encoding.png)
//shkiplist编码的zsort对象使用zet结构作为底层实现
typedef struct zset{
    zskiplist *zsl; //跳表
    dict *dice;     //字典
}zset;
    //字典的键保存元素的值,字典的值保存元素的分值
    //跳表节点的object属性保存元素的成员
    //跳表节点的score属性保存元素的分值
    /*
    这两种数据结构会通过指针来共享相同元素的成员和分值,所以不会产生重复成员和分值,造成内存的浪费。
    */
2.确定编码方式
    - 保存的元素数量小于128
    - 保存的所有元素长度都小于64字节
不满足两个条件时,使用skiplist,fou    

五大数据类型应用场景

- string:因为string 类型是二进制安全的,可以用来存放图片,视频等内容;tring类型的value也可以是数字,可以用作计数器(INCR,DECR),比如分布式环境中统计系统的在线人数,秒杀等。
- hash: value 存放的是键值对,比如可以做单点登录存放用户信息。
- list:  数据类型,可实现简单的消息队列,另外可以利用lrange命令,做基于redis的分
页功能
- set: 由于底层是字典实现的,查找元素特别快,另外set 数据类型不允许重复,利用这两个特性我们可以进行全局去重,比如在用户注册模块,判断用户名是否注册;另外就是利用交集、并集、差集等操作,可以计算共同喜好,全部的喜好,自己独有的喜好等功能。
- zset: 有序的集合,可以做范围查找,排行榜应用,取 TOP N 操作等