一 Redis数据结构-Redis的数据存储及String类型的实现( 三 )

  • 惰性空间释放:惰性空间释放用于优化SDS的字符串缩短操作:当需要缩短SDS保存的字符串时,程序并不立即使用内存重分配来回收缩短后多出来的字节,而是使用free属性将这些字节的数量记录起来,并等待将来使用 。
  • 3.3.3 二进制安全
    C字符串中的字符必须符合某种编码(比如 ASCII,并且除了字符串的末尾之外 , 字符串里面不能包含空字符,否则最先被程序读入的空字符将被误认为是字符串结尾 。
    SDS的API都是二进制安全的(binary-safe):都会以处理二进制的方式来处理SDS存放在buf数组里的数据,程序不会对其中的数据做任何限制、过滤、或者假设 —— 数据在写入时是什么样的,它被读取时就是什么样 。redis不是用这个数组来保存字符,而是用它来保存一系列二进制数据 。
    3.4 SDS结构优化String类型所存储的数据可能会几byte存在大量这种类型数据,但len、free属性的int类型会占用4byte共8byte存储,3.2之后会根据字符串大小使用sdshdr5、sdshdr8、sdshdr16、sdshdr32、sdshdr64数据结构存储,具体结构如下:
    struct __attribute__ ((__packed__)) sdshdr5 {unsigned char flags; /* 3 lsb of type, and 5 msb of string length */char buf[];};struct __attribute__ ((__packed__)) sdshdr8 {uint8_t len; /* used */uint8_t alloc; /* excluding the header and null terminator */unsigned char flags; /* 3 lsb of type, 5 unused bits */char buf[];};struct __attribute__ ((__packed__)) sdshdr16 {uint16_t len; /* used */uint16_t alloc; /* excluding the header and null terminator */unsigned char flags; /* 3 lsb of type, 5 unused bits */char buf[];};struct __attribute__ ((__packed__)) sdshdr32 {uint32_t len; /* used */uint32_t alloc; /* excluding the header and null terminator */unsigned char flags; /* 3 lsb of type, 5 unused bits */char buf[];};struct __attribute__ ((__packed__)) sdshdr64 {uint64_t len; /* used */uint64_t alloc; /* excluding the header and null terminator */unsigned char flags; /* 3 lsb of type, 5 unused bits */char buf[];};
    • unsign char flags:3bit表示类型,5bit表示未使用长度
    • len:表示已使用长度
    • alloc:表示分配空间大小 , 剩余空间大小可以使用alloc - len获得
    3.5 字符集编码redisObject包装存储的value值,通过字符集编码对数据存储进行优化 , string类型的编码方式有如下三种:
    • embstr:CPU每次按Cache Line 64byte读取数据,一个redisObject对象为16byte,为填充64byte大?。?会向后再读取48 byte数据 。但获取实际数据时还需要再通过*ptr指针读取对应内存地址的数据 。而一个sdshdr8属性的信息占用4byte , 其余44byte可以用来存储数据 。如果value值小于44 , byte可以通过一次读取缓存行获取数据 。
      一 Redis数据结构-Redis的数据存储及String类型的实现

      文章插图
    • int:如果SDS小于20位,并且能够转换成整型数字 , redisObject的*ptr指针会直接进行存储 。
      一 Redis数据结构-Redis的数据存储及String类型的实现

      文章插图
    • raw:SDS
      一 Redis数据结构-Redis的数据存储及String类型的实现

      文章插图
    4 总结redis作为k-v数据存储,因查找和操作的时间复杂度都是O(1)和丰富的数据类型及数据结构的优化,了解了这些数据类型和结构更有利于我们平时对于redis的使用 。下一期将对其它常用数据类型List、Hash、Set、Sorted Set所使用的ZipList、QuickList、SkipList做进一步介绍,对于文章中不清晰不准确的地方欢迎大家一起讨论交流 。
    作者:盛旭

    推荐阅读