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。先说结论

  1. 长度小于等于 44 byte,使用 embstr 形式存储,它将 RedisObject 对象头结构和 SDS 对象存在一个连续的空间,使用的是 malloc 方法进行一次分配
  2. 长度大于 44 byte,使用 raw 存储,但存储形式不一样,它需要使用两次 malloc 方法,两个对象头在内存地址上一般是不连续的

为何是44字节?

上面说了redisObject占用16字节,而sds的占用情况如下

1(len) + 1(alloc) + 1(flags) + 1('\0') = 4字节,jemalloc(malloc 实现) 分配的是64字节,

即 64 - 16 - 4 = 44