• Redis基础01-redis的数据结构


    参考书:《redis设计与实现》    

           Redis虽然底层是用C语言写的,但是底层的数据结构并不是直接使用C语言的数据结构,而是自己单独封装的数据结构;

           Redis的底层数据结构由,简单动态字符串,链表,字典,跳跃表,整数集合等几种数据结构组成;

    1.简单动态字符串

    1.定义:

    简单动态字符串:SDS(simple dynamic string)redis 自己构建的;数据结构如下:

    struct sds{ 
        int free;//未使用长度 
        int len;//字符长度
        char buff[];//字符数组
    }

    结尾的一个字节不算在len的长度里面;

    2.SDS和C字符串的差别

       相同点都是n+1的长度,都是以0结尾;

       不同点:1.获取字符串长度复杂度不同;

           2.杜绝缓存区溢出

             3.减少字符修改造成的内存再分配次数;   3.1空间预分配;3.2惰性空间释放;

             4.二进制安全;

             5.兼容部分C字符串;

    2.链表

    1.链表和节点的实现

    struct listNode{
        struct listNode *prev;
        struct listNode *next;
        void *value;
    }
    typeof struct list{
        listNode *head;//第一个
        listNode *tail;//最后一个节点
        unsigned int len;//长度
        void *(*dup)(void *ptr);//复制节点函数
        void (*free)(void *ptr);//节点值释放函数
        int (*match)(void *ptr,void *key)//节点比对函数
     
    }list;

    特点:双端(链表带有pre和next两个指针);

       无环(表头的pre和表尾的next都是NULL);

         带表头指针和表尾指针;

         求链表长度计数器(len是链表节点的计数器)

       多态(dup,free,match三个属性设置特定类型,可以保存不同类型的值)

    3.字典

    1.定义及实现

    字典:又称符号表,关联数组或映射,是一种用于保存键值对的抽象数据结构;
    在字典中,一个字和一个值进行关联,这些键和值就称为键值对;
    
    redis的字典使用哈希表作为底层实现,一个哈希表里面可以有多个哈希表节点,而每个哈希表节点就保存了字典中的一个键值对
    
    • 哈希表
    
    
    typedef struct dictht{
        dictEntry **table;//哈希表数组
        unsigined long size;//哈希表数组大小
        unsigined long sizemask;//哈希表大小掩码,值总是size-1
        unsigined long used;//哈希表数组已有节点的数量
    }

    哈希表节点

    typeof struct dictEntry{
        void *key;//
        union{//
            void *val;
            uint64_tu64;
            int64_ts64;
        } v;
        struct dictEntry *next;//指向另一个哈希表节点的指针,可以将多个哈希值相同的键值对连接在一次
    }

     字典

    typedef struct dist{
        dictype *type;//类型特定函数
        void  *privdata;//私有数据
        dictht ht[2];//哈希表
        in trehashidx;//rehash索引//当rehash不在进行时,值为-1
    }dict;
    
    typedef struc dictType{
        unsigned int (*hashFunction)(const void *key);//计算哈希值的函数
        void *(*keyDup)(void *privdata,const void *key);//复制键的函数
        void *(*valDup)(void *privdata,const void *obj);
        int (*keyCompare)(void *privdata,const void *key1,const void *key2);
        void (*keyDestructor)(void *privdata,void *key);
        void (*valDestructor)(void *privdata,void * obj);
    } dictType ;

    2.哈希算法

    MurmurHash算法来计算键的哈希值。

    3.解决键冲突

        当两个键或者两个以上键分配到redis同一索引的时候,就称为键冲突;使用链地址法来解决键冲突;

    4.rehash重新散列

    目的:为了让平衡因子维持再一个合理的范围,k-v不会太多,也不会太少

    5.渐进式rehash

    分步进行rehash,为字典分配两个哈希表,当对一个哈希表操作时,程序在指定的操作上,会把旧表中的数据带到新的哈希表。到某一点完全实现rehash.

    4.跳跃表

      跳跃表 是一种有序数据结构,它可以在每个节点中维持多个只指向其他节点的指针,从而达到快速访问节点的目的。

      使用的场景:在redis中,一个是实现有序集合键;一个是集群节点中用作内部数据结构;

    1.跳跃表节点


    结构代码:
    
    

    5.整数集合

      当一个集合质保和整数值元素,并且这个集合的元素数量不多时;

    1.整数集合的实现

    整数集合是Redis用于保存整数值的集合抽象数据结构;
    typedef struct intset{
        uint32_t encoding;//决定contents里面保存的数据类型
        uint32_t length;//整数集合包含的元素数量
        int8_t contents[];
    }inset;

    2.升级

      当新元素比整数集合中所有元素的类型都要长时,整数集合需要先升级,再将元素保存到集合里面;

      步骤:1.根据新元素,扩展底层类型;2.将所有元素转换成新元素类型,并保证底层顺序不变;3.将新元素添加到底层里面;

      优点:1.提高灵活性,如果是int_32的就存储相关的元素,如果有int_64的就升级;2.节省内存资源;  

    3.降级

          整数集合不支持降级

    6.压缩列表

      是一种节约内存而开发的顺序型数据结构;

      使用场景:当一个列表项,只有少量数据,且数据比较小,小整数或者短字符的情况下;

    1.压缩列表的构成

     

     

    2.压缩列表节点的构成

    • previous_entry_length:记录前一个结点的长度;

    • encoding:记录content属性所保存的数据和长度;

    • content:保存节点的值;

    3.连锁更新

    每个previous_entry_length属性都记录前一个界定啊的长度:
    如果节点小于254,则需要用1字节长的空间保存这个长度值;如果大于或等于254字节,则用5字节长的空间保存这个长度值







  • 相关阅读:
    概率论
    英语单词每日学习
    网上学习新课程--使用开发板动手进行uboot、内核以及驱动移植
    csdn专家主页
    material of DeepLearning
    I2C协议
    SVN appears to be part of a Subversion 问题心得
    @清晰掉 各种类型32位与64位下各类型长度对比
    超级方便的linux命令手册
    HTTP协议详解(转)
  • 原文地址:https://www.cnblogs.com/perferect/p/12671860.html
Copyright © 2020-2023  润新知