Redis的数据类型和数据结构

数据类型数据结构数据结构应用场景
StringSDS简单动态字符串存储字符串信息
ListLinkedlist、Ziplist双向链表、压缩列表消息队列或栈的实现
HashHashtable、Ziplist哈希表、压缩列表存储键值对信息
SetHashtable、Intset哈希表、整数集合存储非重复元素
ZsetZiplist、SkipList压缩列表、跳表热搜榜、基于Timeline的排序
Geospatial————用于获取地理位置信息
Hyperloglog————统计基数个数
Bitmap————活跃(非活跃)、在线(离线)等只有两种状态的情景

一、SDS

struct __attribute__ ((__packed__)) sdshdr16 {
    uint16_t len;
    uint16_t alloc; 
    unsigned char flags; 
    char buf[];
};


struct __attribute__ ((__packed__)) sdshdr32 {
    uint32_t len;
    uint32_t alloc; 
    unsigned char flags;
    char buf[];
};

在这里插入图片描述

二、Linkedlist

1.链表结点

typedef struct listNode {
    //前置节点
    struct listNode *prev;
    //后置节点
    struct listNode *next;
    //节点的值
    void *value;
} listNode;

2.链表结构

typedef struct list {
    //链表头节点
    listNode *head;
    //链表尾节点
    listNode *tail;
    //节点值复制函数
    void *(*dup)(void *ptr);
    //节点值释放函数
    void (*free)(void *ptr);
    //节点值比较函数
    int (*match)(void *ptr, void *key);
    //链表节点数量
    unsigned long len;
} list;

在这里插入图片描述

三、Ziplist

在这里插入图片描述

  • zlbytes,记录整个压缩列表占用的内存字节数;
  • zltail,记录压缩列表「尾部」节点的偏移量;
  • zllen,记录压缩列表包含的节点数量;
  • zlend,标记压缩列表尾部的结束点,固定值 0xFF(十进制255)
  • prevlen,记录「前一个节点」的长度;
  • encoding,记录当前节点的数据类型以及长度;
  • data,保存当前节点的实际数据;

四、Hashtable

1.哈希表结点

typedef struct dictEntry {
    //键值对中的键
    void *key;
    //键值对中的值
    union {
        void *val;
        uint64_t u64;
        int64_t s64;
        double d;
    } v;
    //指向下一个哈希表节点,形成链表
    struct dictEntry *next;
} dictEntry;

2.哈希表结构

typedef struct dictht {
    //哈希表数组
    dictEntry **table;
    //哈希表大小
    unsigned long size;  
    //哈希表大小掩码,用于计算索引值
    unsigned long sizemask;
    //该哈希表已有的节点数量
    unsigned long used;
} dictht;

在这里插入图片描述

五、Intset

typedef struct intset {
    //编码方式
    uint32_t encoding;
    //集合包含的元素数量
    uint32_t length;
    //保存元素的数组
    int8_t contents[];
} intset;

六、Skiplist

1.跳表结点

typedef struct zskiplistNode {
    //Zset 对象的元素值
    sds ele;
    //元素权重值
    double score;
    //后向指针
    struct zskiplistNode *backward;

    //节点的level数组,保存每层上的前向指针和跨度
    struct zskiplistLevel {
        struct zskiplistNode *forward;
        unsigned long span;
    } level[];
} zskiplistNode;

2.跳表结构

typedef struct zskiplist {
    struct zskiplistNode *header, *tail;
    unsigned long length;
    int level;
} zskiplist;

在这里插入图片描述

七、Quicklist

  在 Redis 3.0 之前,List 对象的底层数据结构是双向链表或者压缩列表。在 Redis 3.2 的时候,List 对象的底层改由 quicklist 数据结构实现。其实 quicklist 就是「双向链表 + 压缩列表」组合,因为一个 quicklist 就是一个链表,而链表中的每个元素又是一个压缩列表。

1.quicklist结点

typedef struct quicklistNode {
    //前一个quicklistNode
    struct quicklistNode *prev;     //前一个quicklistNode
    //下一个quicklistNode
    struct quicklistNode *next;     //后一个quicklistNode
    //quicklistNode指向的压缩列表
    unsigned char *zl;              
    //压缩列表的字节大小
    unsigned int sz;                
    //压缩列表的元素个数
    unsigned int count : 16;        //ziplist中的元素个数 
    ....
} quicklistNode;

2.quicklist结构

typedef struct quicklist {
    //quicklist的链表头
    quicklistNode *head;      //quicklist的链表头
    //quicklist的链表头
    quicklistNode *tail; 
    //所有压缩列表中的总元素个数
    unsigned long count;
    //quicklistNodes的个数
    unsigned long len;       
    ...
} quicklist;

在这里插入图片描述

八、Listpack

  quicklist 虽然通过控制 quicklistNode 结构里的压缩列表的大小或者元素个数,来减少连锁更新带来的性能影响,但是并没有完全解决连锁更新的问题。因为 quicklistNode 还是用了压缩列表来保存元素,压缩列表连锁更新的问题,来源于它的结构设计,所以要想彻底解决这个问题,需要设计一个新的数据结构。于是,Redis 在 5.0 新设计一个数据结构叫 listpack,目的是替代压缩列表,它最大特点是 listpack 中每个节点不再包含前一个节点的长度了。

在这里插入图片描述

  • encoding,定义元素的编码类型,会对不同长度的整数和字符串进行编码
  • data,存储的数据
  • len,encoding+data字段的长度
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Malax

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值