zoukankan      html  css  js  c++  java
  • Redis字符串结构

    【SDS结构】
    Redis中字符串的结构叫SDS,即Simple Dynamic String。它的结构是一个带长度信息的字节数组。

    struct SDS<T>{
    T capacity;
    T len;
    byte flags;
    byte[] content;
    }

    1.capacity>=len
    content中存储了真正的字符串内容,capacity和len表示分配数组的长度和字符串的实际长度。
    如图所示,除了包含当前的len长度字符串的字节内容,还会冗余一部分空间为后续的追加准备:

    但需要注意的是,创建字符串的时候,len=capacity,不会留冗余空间,因为绝大多数场景下,我们不会使用append操作来修改字符串。
    2.扩容规则
    之前提到过字符串的长度在1M以下是翻倍扩容,大于1M时扩容每次增加1M,到512M封顶。
    当字符串长度增加时(append新内容),直接追加到冗余的空间,当冗余空间不够时,就会分配新数组,然后将旧的数组分配到新数组中。
    3.T
    SDS结构中使用了泛型,也是为了节省空间。当字符串比较短时,这里分配的记录长度的结构是byte(1个字节)或者short(2个字节)...不同长度的字符串用不同的结构体表示。

    【embstr VS raw】
    长度特别短时,使用embstr形式存储,而长度超过44个字节时,使用raw形式存储。

    要解释为什么长度超过44个字节就要变换存储形式,我们要了解这两种存储形式的真正面貌。
    先来看Redis对象头,这个对象头是所有的Redis对象都会有的结构,这个结构也是会占用空间的:

    struct RedisObject{
    int4 type; //4bits
    int4 encoding; //4bits
    int24 lru; //24bits
    int32 refcount; //4bytes
    void *ptr; //8bytes, 64-bit system
    } robj;

    不同对象具有不同的类型type(4bit)。同一个类型的type会有不同的存储形式encoding(4bit)。为了记录对象的LRU信息,使用了24个bit来记录信息。每个对象都有个引用计数,当引用计数为零时,对象就会被销毁,内存被回收。ptr指针将指向对象内容(body)的具体存储位置。这样一个RedisObject对象头结构需要占据16个字节的存储空间。
    而SDS结构体(body)中,算capacity和len的类型为byte,flags类型也为byte所以就算byte[] content为0,最少也是3个字节,所以和对象头加起来最小空间占用为19个字节。
    内存分配器jemalloc,tcmalloc等分配内存大小的单位是2的幂次方,所以为了能够容纳一个完整的最小embstr结构,最少分配32个字节。如果字符串稍微长一点,就是64个字节。整体超过64个字节,Redis就会认为这是一个大字符串,即使用raw结构存储。
    而64个字节,除开头结构加body中的信息记录字段19个字节,另外content字符串数组的结尾必须为NULL占用1个字节,所以embstr结构中最多能够容纳44个字节的字符串。结构如图:

    【参考】

    《Redis深度历险 核心原理与应用实践》

  • 相关阅读:
    网页加速的14条优化法则 网站开发与优化
    .NET在后置代码中输入JS提示语句(背景不会变白)
    C语言变量声明内存分配
    SQL Server Hosting Toolkit
    An established connection was aborted by the software in your host machine
    C语言程序设计 2009春季考试时间和地点
    C语言程序设计 函数递归调用示例
    让.Net 程序脱离.net framework框架运行
    C语言程序设计 答疑安排(2009春季 110周) 有变动
    软件测试技术,软件项目管理 实验时间安排 2009春季
  • 原文地址:https://www.cnblogs.com/bruceChan0018/p/15800019.html
Copyright © 2011-2022 走看看