redis中的无论是哪种类型,都不会直接存储,而是通过redisObject对象进行存储。
一、redisObject
首先我们来看看他的数据结构
typedef struct redisObject
{
unsigned type:4;
unsigned encoding:4;
unsigned lru:REDIS_LRU_BITS; /* lru time (relative to server.lruclock) */
int refcount;
void *ptr;
}
他标定了数据的类型、编码方式、lru时间(记录了该对象最后一次被命令访问的时间)、引用计数(帮助内存回收,当被创建时,初始值为1,被其他对象引用则加1,减少引用则减1)以及指向对象的地址。
redisObject占用空间:4 + 4 + 24(lru) + 32(refcount) + 64(*ptr) = 128bits = 16字节
基本上,数据的存储地址与redisObject所存储的地址是分开的,唯有SDS不一样。SDS是redis中 string 得数据类型,成为简单动态字符串,在c++的 string 类型上做了延伸,可以看一下redis的string类型SDS。
1. SDS(Redis版本 >= 3.2)
sds编码形式有三种:int、embstr(3.0 版本被引入)、raw。先说结论
-
长度小于等于 44 byte,使用 embstr 形式存储,它将 RedisObject 对象头结构和 SDS 对象存在一个连续的空间,使用的是 malloc 方法进行一次分配
-
长度大于 44 byte,使用 raw 存储,但存储形式不一样,它需要使用两次 malloc 方法,两个对象头在内存地址上一般是不连续的
为何是44字节?
上面说了redisObject占用16字节,而sds的占用情况如下
1(len) + 1(alloc) + 1(flags) + 1('\0') = 4字节,jemalloc(malloc 实现) 分配的是64字节,
即 64 - 16 - 4 = 44