Redis存储结构
/*
* Redis 对象
*/
typedef struct redisObject {
// 类型
unsigned type:4;
// 对齐位
unsigned notused:2;
// 编码方式
unsigned encoding:4;
// LRU 时间(相对于 server.lruclock)
unsigned lru:22;
// 引用计数
int refcount;
// 指向对象的值
void *ptr;
} robj;
type、 encoding 和 ptr 是最重要的三个属性.
type 记录了对象所保存的值的类型, 它的值可能是以下常量的其中一个
/*
* 对象类型
*/
#define REDIS_STRING 0 // 字符串
#define REDIS_LIST 1 // 列表
#define REDIS_SET 2 // 集合
#define REDIS_ZSET 3 // 有序集
#define REDIS_HASH 4 // 哈希表
encoding 记录了对象所保存的值的编码, 它的值可能是以下常量的其中一个
/*
* 对象编码
*/
#define REDIS_ENCODING_RAW 0 // 编码为字符串
#define REDIS_ENCODING_INT 1 // 编码为整数
#define REDIS_ENCODING_HT 2 // 编码为哈希表
#define REDIS_ENCODING_ZIPMAP 3 // 编码为 zipmap
#define REDIS_ENCODING_LINKEDLIST 4 // 编码为双端链表
#define REDIS_ENCODING_ZIPLIST 5 // 编码为压缩列表
#define REDIS_ENCODING_INTSET 6 // 编码为整数集合
#define REDIS_ENCODING_SKIPLIST 7 // 编码为跳跃表
也就是通过 encoding 来对键进行不同的操作.
ptr 是一个指针, 指向实际保存值的数据结构, 这个数据结构由 type 属性和 encoding 属性决定
redisObject 、Redis 所有数据类型、以及 Redis 所有编码方式(底层实现)三者之间的关系

字符串
REDIS_ENCODING_INT编码:保存long 型的64位有符号整数(长度<20)
REDIS_ENCODING_RAW编码:保存长度大于39字节的字符串 (3.2版本后调整为44个字节)
能用数值不用字符串表示,尽量使用短字符串
应用:k-v、计数、分布式锁
列表
REDIS_ENCODING_ZIPLIST(压缩列表)
REDIS_ENCODING_LINKEDLIST(双端链表)(3.2版本后都用quicklist实现)
压缩链表—》双端链表转换条件:
list-max-ziplist-value 64 (默认值)
list-max-ziplist-entries 512 (默认值)
双端链表:双端、无环、带链表长度计算器、多态;内存开销比较大,内存碎片
压缩链表:节省内存
应用:消息队列、数据分页缓存
哈希表
REDIS_ENCODING_ZIPLIST(压缩列表)
REDIS_ENCODING_HT(哈希字典)
编码转换:
元素个数小于 hash-max-ziplist-entries 配置(默认 512 个),同时值都小于 hash-max-ziplist-value 配置(默认 64 字节)时,使用 REDIS_ENCODING_ZIPLIST作为哈希的内部实现
不能满足这两个条件的哈希对象需要使用 REDIS_ENCODING_HT编码
编码特点对比:
REDIS_ENCODING_HT编码:字典结构,读写速度快O(1),内存占用多
REDIS_ENCODING_ZIPLIST编码:空间连续,占用内存少
应用:
购物车:可以实现以用户Id,商品Id为field,商品数量为value,恰好构成了购物车的3个要素。
存储对象:hash类型的(key, field, value)的结构与对象的(对象id, 属性, 值)的结构相似,也可以用来存储对象
集合
REDIS_ENCODING_INTSET(整数集合)
REDIS_ENCODING_HT(哈希字典)
编码转换:使用intset需要同时满足以下条件
1.集合对象保存的所有元素都是整数且位数<20个字符;
2.集合对象保存的元素数量不超过 512 个(可通过set-max-intset-entries配置项修改)
编码特点对比:
intset的底层实现为数组,该数组中的元素有序、无重复的存放,更好的节省内存
hashtable添加删除元素的时间复杂度为O(1),适合存储大量数据
应用:
1、标签:比如我们博客网站常常使用到的兴趣标签,把一个个有着相同爱好,关注类似内容的用户利用一个标签把他们进行归并。
2、共同好友功能,共同喜好,或者可以引申到二度好友之类的扩展应用。(SINTER命令)
3、统计网站的独立IP。利用set集合当中元素不唯一性,可以快速实时统计访问网站的独立IP。
有序集合
REDIS_ENCODING_ZIPLIST(压缩列表)
REDIS_ENCODING_SKIPLIST(跳跃表)
编码转换:使用ZIPLIST需要同时满足以下条件
元素数量小于128个
所有member的长度都小于64字节
skiplist编码的底层是一个命名为zset的结构体,包含一个字典和一个跳跃表;是一种用于解决查找问题的一种数据结构
编码特点对比:
同样是内存占用与查找速度的区别
应用:排行榜
网友评论