Redis基本数据结构

2021-01-23  本文已影响0人  鸿雁长飞光不度

SDS(简单动态字符串)

定义


struct sdshdr {
    //记录buf数组中已使用的字节数量
    int len;
    //记录buf数组中未使用的字节数量
    int free;
    //字节数组,用于保存字符串
    char buf[];
}

应用场景

表示除了字面量以外的字符串。

对比C字符串优点

C字符串 SDS
O(N)获取字符串长度 O(1)获取长度
API不安全,可能缓冲区溢出 API安全不会造成缓冲区溢出
修改字符串N次必然执行N次内存重分配 最多执行N次
只保存文本数据 可以保存文本或者二进制
使用string.h所有函数 可使用一部分函数

链表

定义

typedef struct listNode{
    struct ListNode * prev;
    
    struct ListNode *next;
    
    void * value;
} listNode;

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

字典 (symbol table)

哈希表

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

哈希节点

typedef struct dictEntry{
    void * key;
    union {
        void * val;
        uint64 _tu64;
        int64 _ts64;
    }v;
    //指向下个哈希表节点,形成链表
    strcut dictEntry *next;
}dictEntry

redis的字典

typedef struct dict{
    //type和privdata属性是针对不同类型的键值对,创建多态字典。
    dictType * type;
    void * privdata;
    // 哈希表
    dictht ht2[];
    // rehash时候的索引值,没有rehash操作等于-1
    int trehashidx;
}
typedef struct dictType{
    //计算哈希值的函数
    unsigned int (*hashFunction)(const void * key);
    //复制key的函数
    void *(*keyDup)(void*privdata,const void*key);
    // 复制值的函数
    void*(*valDup)(void*privdata,const void *obj);
    //对比key
    int*(*keyCompare)(void *privdata,void*key1,void*key2);
    //销毁key
    void(*keyDestruct)(void * privdata,void *key);
     //销毁value
    void(*valDestruct)(void * privdata,void *obj);
    
}dictType
{
    "id":1234,
    "shop_id":'12345'
}

字典被广泛用于Redis的各种功能,包括数据库和哈希键。

跳跃表

typedef struct zskiplistNode{
    
    struct zskiplistLevel {
        // 前进指针
        struct zskiplistNode * forward;
        //跨度
        unsigned int span;
    }level[];
    // 后退指针
    struct zskiplistNode * backward;
    // 分值
    double score;
    // 成员对象
    robj * obj;
}

跳跃表

typedef struct zskiplist {
    //表头节点和表尾节点
    struct skiplistNode * header, *tail;
    // 表中节点的数量
    unsigned long length;
    // 表中层数最大的节点的层数
    int level;
}zskiplist;

实现有序集合、集群节点中作内部数据结构。每次生成一个节点都会根据幂次定律确定层数(越大的数据出现的概率越小),跨度用来计算排位,再查找节点的过程中,将沿途访问过的所有跨度累计起来,就是目标节点再跳跃表中的排位。

整数集合

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

整数集合是集合键的底层实现之一,底层以实现为数组,数组以有序、无重复的方式保存元素,有需要的时候会根据新添加元素的类型改变数组类型。只支持类型升级
不支持降级操作。

压缩列表

压缩列表是列表键和哈希键的底层实现之一,当一个列表键只包含少量的列表项目,
并且每个列表项要么是小整数值,要么就是长度比较短的字符串。redis就会使用压缩列表做底层实现。

属性 类型 长度 用途
zlbytes uint32_t 4字节 记录占用的内存字节数:对压缩列表进行内存分配
zltail uint32_t 4字节 记录压缩列表表尾节点距离起始地址有多少字节。
zllen uint16_t 2字节 记录节点数量,小于uint16_max有效,等于时需要遍历计算。
entryX 列表节点 不定 压缩列表包含的各个节点,节点长度由节点保存的内容决定
zlend uint8_t 1字节 特殊值,标记压缩列表的末端

压缩列表节点:

压缩列表是为节约内存开发的顺序数据结构,被用作列表键和哈希键的底层实现之一,添加新的节点到压缩列表或者删除节点,可能会引发连锁更新操作,但是出现的几率不高。


Redis对象

Redis对象基于上述基本数据结构组合实现,可以根据不同的场景设置不同的数据结构实现,从而优化对象再不同场景下的使用效率。Redis对象实现了基于引用技术的内存回收机制,程序不再使用某个对象的时候,这个对象所占用的内存就会被释放,并且基于引用计数实现了对象共享机制。Redis对象带有访问时间记录信息,计算数据库键空转市场,再服务器启用maxmemmoery功能,空转时长较大的key会被优先删除。


typedef struct redusObject {
    // 类型
    unsigned type:4;
    // 编码
    unsigned encoding:4;
    // 指向底层实现数据结构的指针
    void *ptr;
}
类型 编码 对象
REDIS_STRING REDIS_ENCODING_INT 使用整数值实现的字符串对象
REDIS_STRING REDIS_ENCODING_EMBSTR 使用embstr编码的简单动态字符串实现的字符串对象
REDIS_STRING REDIS_ENCODING_RAW 使用简单冬天字符串实现的字符串对象
REDIS_LIST REDIS_ENCODING_ZIPLIST 使用压缩列表实现的列表对象
REDIS_LIST REDIS_ENCODING_LINKEDLIST 使用双端链表实现的列表对象
REDIS_HASH REDIS_ENCODING_ZIPLIST 使用压缩列表实现的哈希对象
REDIS_HASH REDIS_ENCODING_HT 使用字段实现的哈希对象
REDIS_SET REDIS_ENCODING_INTSET 使用整数集合实现的集合对象
REDIS_SET REDIS_ENCODING_HT 使用字典实现的集合对象
REDIS_ZSET REDIS_ENCODING_ZIPLIST 使用压缩列表实现的有序集合
REDIS_ZSET REDIS_ENCODING_SKIPLIST 使用跳跃表和字典实现的有序集对象
上一篇下一篇

猜你喜欢

热点阅读