zoukankan      html  css  js  c++  java
  • Redis学习笔记之底层数据结构

    1.简单动态字符串(simple dynamic string, SDS)

      定义:

      struct sdshdr {

             int len;//记录buf中使用的字节数量

             int free;//记录buf中未使用的字节数量

             char buf[];//字节数组,用于保存字符串

             //buf字节数组以’’结束,但是’’不计算在len之中,对于用户来说是透明的

      }

      SDS与C中的字符串相比,优势在于:

             O(1)时间复杂度获取字符串长度;杜绝缓冲区溢出(每次修改buf时会检查空间是否充足);提高修改字符串的效率(空间预分配和惰性释放空间,客观的说会浪费一定的空间,空间换时间);二进制安全(支持字符串中有空字符串);

    2.链表和链表节点

      定义:双向链表的节点

      typedef struct listNode {

               struct listNode *prev;//前置节点

               struct listNode *next;//后置节点

               void *value;//节点的值

      } listNode;

      用如下结构来管理链表:

      typedef struct list {

               listNode *head;//链表头

               listNode *tail;//链表尾

               unsigned long len;//链表节点数

               void *(*dup) (void *ptr);//节点值复制函数

               void (*free) (void *ptr);//节点值释放函数

               int (*match) (void *ptr, void *key);//节点值对比函数

      } list;

      优点:很多值或者节点都存储起来了,访问节点长度、尾节点等时间复杂度降低,多态(value的类型是void*)

    3.字典——哈希键的底层实现之一

      哈希表结构:

      typedef struct dictht {

               dictEntry **table;//哈希表数组

               unsigned long size;//哈希表大小

               unsigned long sizemask;//哈希表大小掩码

               unsigned long used;//哈希表已有节点数量

      } dictht;

      哈希表节点结构:

      type struct dictEntry {

               void *key;//

               union {//

                      void *val;

                      unit64_tu64;

                      int64_ts64;

               } v;

               struct dictEntry *next;//指向下个哈希表节点,形成链表

      } dictEntry;

      字典结构:

      typedef struct dict {

                    dictType *type;//字典类型,为创建多态字典

                    void *privdata;//保存需要传给类型特性函数的参数

                    dictht ht[2];//字典只使用ht[0],rehash时才使用ht[1]

                    int rehashidx;//记录了rehash的进度,默认是-1

      } dict;

      Redis的哈希表使用链地址法,rehash时将ht[0]上的值rehash到ht[1]上(涉及ht[1]的空间分配大小问题),然后把ht[1]作为ht[0],把ht[1]设置为空白哈希表

      渐进式rehash:在每一次增删改操作的时候,将ht[0]上对应的键值对写到ht[1]上,在某个时间点时,ht[0]上的值全部写到ht[1]上

    4.跳跃表

      实现:主要由两个结构组成,zskiplist用于保存跳跃表信息,zskiplistNode用于表示跳跃表节点;每一个zskiplistNode有若干(1~32随机)层(每一层都有前进指针和跨度),还有后退指针、分值、成员对象obj;成员对象唯一,分值可相同;节点按照分值的大小进行排序,分值相同时按照成员对象的大小排序。

      用处:有序集合、集群节点中用作内部数据结构

    5.整数集合

      定义:

      typedef struct intset {

                    uint32_t encoding;

                    uint32_t length;

                    int8_t contents[];

      } intset;

      重点:整数集合升级,contents中保存的数据可能是16位、32位、64位的,会根据存入数据的位数对集合进行升级;不支持降级

      用处:集合元素全是整数的情况

    6.压缩列表——列表键和哈希键的底层实现之一

      结构:zlbytes zltail zllen entry1 entry2…entryN zlend

      zlbytes:uint32_t,记录整个压缩列表的字节数

      zltail:uint32_t,记录压缩列表尾节点距离列表首地址有多少个字节

      zllen:uint16_t,记录压缩列表包含的节点数量

      entryN:压缩列表包含的节点

              previous_entry_length   前一节点的大小

              encoding   记录了节点content所保存的数据的类型和值

              content   节点的值

      zlend:uint8_t,特殊值0XFF,用于标记压缩列表的末端

      连锁更新:节点中previous_entry_length的长度是根据值的大小确定的,所以当更新前一节点的长度时,这个值所占的字节数可能会引起改变,因此需要更新更新节点的后续节点。如果更新节点的后续节点全部都需要更新,那么效率会很低,但是需要全部节点更新的概率极低,因此不需要考虑对效率的影响。

  • 相关阅读:
    js 实现商品放大镜效果
    Angular.js数据绑定时自动转义html标签及内容
    Sublime 快捷键一览表
    这么牛的简历,你见过么?
    正向代理与反向代理
    负载均衡
    redis搭建与安装
    svn服务配置和日常维护命令
    Mysql导出导入
    linux搭建svn服务器
  • 原文地址:https://www.cnblogs.com/songxh-scse/p/6692413.html
Copyright © 2011-2022 走看看