redis——数据结构

    • inset
        • 扩容
    • skipList
    • redisObject
    • list
    • set
    • hash
    • zset

inset

typedef struct intset {
    uint32_t encoding; //编码方式 4B 16(2B) 32(3B) 64(4B)
    uint32_t length; // 元素个数  4B
    int8_t contents[];
} intset;

扩容

  • 修改编码格式
  • 计算长度,申请空间
  • 倒序,将数组内容复制到新位置
  • 添加新元素
  • 修改header:encoding,length

skipList

  • 元素升序排列。按score和ele排序
  • 一个节点多个指针,不同跨度,最多32级指针。
  • 便于排序查找,增删改查效率基本等于红黑树。
/* ZSETs use a specialized version of Skiplists */
typedef struct zskiplistNode {
    sds ele;//值
    double score;//节点分数,排序查找使用
    struct zskiplistNode *backward;//前一个指针
    struct zskiplistLevel {
        struct zskiplistNode *forward;//下一个节点指针
        unsigned long span;//索引跨度
    } level[];//多级索引,最多32级
} zskiplistNode;

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

redisObject

将之前的底层数据结构,包装为redisObject使用
header:16B

struct redisObject {
    unsigned type:4;//对象类型
    unsigned encoding:4;//编码方式
    unsigned lru:LRU_BITS; /* 最后一次被访问的时间,判断空闲太久的key
    						* LRU time (relative to global lru_clock) or
                            * LFU data (least significant 8 bits frequency
                            * and most significant 16 bits access time). */
    int refcount;//对象引用计数器
    void *ptr;//指针,指向不同数据类型的数据,真实数据
};

大量string数据每一个都需要一个对象头,占大量空间
可以使用list等集合的形式,解约对象头的空间

  • sds
    sds长度小于44B,则redisObject和sds共同申请一块连续空间,少一次内存分配,效率高
    大于44B,则分开申请空间,不要求连续
    如果存储的字符串为整数,则直接存在ptr指针的位置(8B),无需sds

list

linkedList:双端链表,内存占用高,内存碎片多
zipList:压缩列表,双端访问,内存占用低,存储上限低
quickList=linkedList+zipList。多个zipList,双端访问,内存占用低,存储上限高

set

dict:key存值,value为null,内存占用大
intSet

hash

ziplist,相邻两个节点,一个存key,一个存value
数据量大时转为dict

zset

可排序set
根据score(value)排序,member(key)唯一
数据存两份,耗费内存

typedef struct zset {
    dict *dict;//唯一
    zskiplist *zsl;//排序
} zset;

redis——数据结构_第1张图片
数据量小(128),且每个元素大小较小(64B),则使用zipList。存储时按score升序排。查找遍历

你可能感兴趣的:(redis,数据结构,redis,链表)