zoukankan      html  css  js  c++  java
  • 【Redis】Redis数据类型底层结构

    参考:《Redis设计与实现》

    RedisObject

    Redis底层的所有数据结构:都是基于对象的;RedisObject

    • 类型;
    • 编码;
    • 指向实际数据的指针;
    typedef struct redisObject{
        // 类型
        unsigned type:4;
        // 编码
        unsigned encoding:4;
        // 指向底层实现数据结构的指针
        void *ptr;
    }
    
    • type:记录是什么类型(String,List,Hah表,set,Zset)

    • encoding:对象使用的编码;

    • *ptr:数据指针(比如String,ptr就指向了一个SDS动态字符串)

    一个String类型数据如下图:

    String

    Redis的字符串底层使用SDS(动态字符串),而不是C语言的字符串;

    // SDS的定义
    strcut sdshdr{
        // 记录字符串长度
        int len;
        // 记录未使用的buf;
        int free;
        // 字符串数组,存放实际的字符串
        char buf[];
    }
    

    为什么不使用C的字符串?

    C字符串 SDS
    获取字符串长度复杂度:O(N) 获取字符串长度复杂度:O(1)
    不安全,可能缓冲区溢出 安全,不会溢出,不会泄露
    修改字符串,必须执行N次内存的重新分配 修改字符串,除非是全部改需要N次内存分配

    跳跃表

    是一种有序数据结构,通过每个节点中维持多个指向其他节点指针,达到快速访问;

    多个节点指针:意味着跳跃表的层数;

    • 层:每个节点的多个指针,是一个指针集合List;同层之前指针关联;
    • 前进指针:每一层的从头指向后面的指针;
    • 跨度:记录两个节点间的距离;
    • 后退指针:每个节点,只有一个后退指针,也就是全部后退指针相当于一个单链表;
    • 分值Score:跳跃表,按照Score大小排序;
    • 成员:也就是此节点的value;

    复杂度:增删改查O(logn),最坏O(n)

    结构源码:

    // zset结构
    typedef struct zskiplist{
        // 头节点,尾节点
        structz skiplisNode *header , *tail;
        // 节点数量
        unsigned long length;
        // 最大的节点层数;
        int level;
    }
    
    // 跳跃表的结构
    typedef struct skiplisNode{
    	// 层:是一个节点集合
        struct zskiplistLevel{
            // 前进指针
            struct zskiplistNode *forward;
            // 跨度
            unsigned int span;
        } level[];
    	// 后退指针
        struct zskiplistNode *backward;
        // 分值
        double score;
        // 成员对象
        robj *obj;
    
    }
    

    Hash表

    RedisObject中的ptr指针,指向的就是哈希对象:

    typedef struct dict{
        // 指向对哈希表操作的函数
        dictType *type;
        // 私有数据
        void *privdata;
        // ht[1]指向真正的哈希表结构,ht[2]用于备用扩容,指向正在扩容的哈希表
        dictht ht[2];
        // 是否在rehash:如果不在rehash,此值为-1;
        int trehashidx;
    }
    

    哈希表:

    typedef struct dictht{
        // 哈希数组
        dictEntry **table;
        // 哈希表大小
        unsigned long size;
        // 记录尾部:size-1
        unsigned long sizemask;
        // 已使用的大小
        unsigned long used;
    }
    

    哈希节点对象:

    typedef struct dictEntry{
        // key
        void *key;
        // value
        union{
            void *val;
            unit64_tu64;
            int64_ts64;
        } v;
        // next指针
        struct dictEntry *next;
    } dictEntry;
    

    • 上面的整个哈希表,出现了哈希冲突,使用链地址法解决哈希冲突;

    哈希表的扩容

  • 相关阅读:
    firefox ajax async 弹出窗口提示阻止
    Spring加载resource时classpath*:与classpath:的区别(转)
    超链接的href属性 js调用
    jquery easyui tabs layout 记录
    PostgreSQL 中的递归查询 与oracle 的比较
    将字符串中的中文(英文)字符串转化为阿拉伯数字
    用CSS控制文字的宽度,超过省略号代替(转)
    制作gridview 固定列的2种简单解决方案
    自制树型控件(DataGrid) 支持多种响应
    备忘: select 对象的操作js(转)
  • 原文地址:https://www.cnblogs.com/mussessein/p/13247057.html
Copyright © 2011-2022 走看看