美文网首页
Redis底层数据结构

Redis底层数据结构

作者: 晚歌歌 | 来源:发表于2021-07-07 15:42 被阅读0次

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 所有编码方式(底层实现)三者之间的关系

image.png

字符串

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的结构体,包含一个字典和一个跳跃表;是一种用于解决查找问题的一种数据结构

编码特点对比:
同样是内存占用与查找速度的区别

应用:排行榜

相关文章

网友评论

      本文标题:Redis底层数据结构

      本文链接:https://www.haomeiwen.com/subject/filtpltx.html