zoukankan      html  css  js  c++  java
  • redis基本数据类型和对应的底层数据结构

    Redis的数据类型包含string,list,hash,set,sorted set。

    在Redis中,KV对是以dictEntry的形式来存储的,dictEntry是由key(key是字符串,Redis 没有直接使用 C 的字符数组,而是存储在自定义的 SDS 中)、value(redisObject)和指针组成的。

    为什么要用SDS:
    我们知道,C 语言本身没有字符串类型(只能用字符数组 char[]实现)。
    1、使用字符数组必须先给目标变量分配足够的空间,否则可能会溢出。
    2、如果要获取字符长度,必须遍历字符数组,时间复杂度是 O(n)。
    3、C 字符串长度的变更会对字符数组做内存重分配。
    4、通过从字符串开始到结尾碰到的第一个''来标记字符串的结束,因此不能保存图片、音频、视频、压缩文件等二进制(bytes)保存的内容,二进制不安全。
    SDS 的特点:
    1、不用担心内存溢出问题,如果需要会对 SDS 进行扩容。
    2、获取字符串长度时间复杂度为 O(1),因为定义了 len 属性。
    3、通过“空间预分配”( sdsMakeRoomFor)和“惰性空间释放”,防止多次重分配内存。
    4、判断是否结束的标志是 len 属性(它同样以''结尾是因为这样就可以使用 C 语言中函数库操作字符串的函数了),可以包含''。 

    redisObject 定义在 src/server.h 文件中,具体代码如下:
    typedef struct redisObject {
        // 类型:string,list,hash,set,sorted set(5种基本类型)
        unsigned type:4;    
        // 不使用(对齐位)
        unsigned notused:2;
        // 编码方式
        unsigned encoding:4;
        // LRU 时间(相对于 server.lruclock)
        unsigned lru:22;
        // 引用计数
        int refcount;
        // 指向对象的值
        void *ptr;
    } robj;

    type表示了该对象的数据类型(即上面五个中的一个)。但为了提高存储效率与程序执行效率,每种对象的底层数据结构实现都可能不止一种。encoding就表示了对象底层所使用的编码。下面先介绍每种底层数据结构的实现,再介绍每种对象类型都用了什么底层结构并分析他们之间的关系。
         Redis对象底层数据结构共八种:
         编码常量 编码所对应的底层数据结构 
         REDIS_ENCODING_INT(long 类型的整数)
         REDIS_ENCODING_EMBSTR embstr (编码的简单动态字符串) 
         REDIS_ENCODING_RAW (简单动态字符串) 
         REDIS_ENCODING_HT (字典) 
         REDIS_ENCODING_LINKEDLIST (双端链表) 
         REDIS_ENCODING_ZIPLIST (压缩列表) 
         REDIS_ENCODING_INTSET (整数集合) 
         REDIS_ENCODING_SKIPLIST (跳跃表和字典)

    一、String

    字符串对象的底层实现可以是int、raw、embstr。

    1、int,存储 8 个字节的长整型(long,2^63-1)。

    2、embstr, 代表 embstr 格式的 SDS(Simple Dynamic String 简单动态字符串),存储小于 44 个字节的字符串。

    3、raw,存储大于 44 个字节的字符串(3.2 版本之前是 39 字节)
     
    embstr 和 raw 的区别?
    embstr 的使用只分配一次内存空间(因为 RedisObject 和 SDS 是连续的),而 raw 需要分配两次内存空间(分别为 RedisObject 和 SDS 分配空间)。因此与 raw 相比,embstr 的好处在于创建时少分配一次空间,删除时少释放一次空间,以及对象的所有数据连在一起寻找方便。而 embstr 的坏处也很明显,如果字符串的长度增加需要重新分配内存时,整个 RedisObject 和 SDS 都需要重新分配空间,因此 Redis 中的 embstr 实现为只读。
  • 相关阅读:
    kafka原理深入研究 (转 )
    redis——持久化篇
    IDEA 配置环境和相关工具整理(新手入门)
    Spring Data JPA(官方文档翻译)
    springboot:spring data jpa介绍
    JDK8-十大新特性-附demo
    JDK8新特性一览
    Maven中的pom.xml配置文件详解
    数据库面试题(更新中...)
    互联网协议系列
  • 原文地址:https://www.cnblogs.com/panning/p/9644835.html
Copyright © 2011-2022 走看看