Redis数据结构底层存储

  • 时间:
  • 浏览:0
  • 来源:跟我学网络

关于redis内部实现,涉及内存内存分配器(jemalloc),简单动态字符串(sds),5种对象类型及内部编码,redisObject。

  • dictEntry: 每个键值对都会对应这个结构,存储指向key、value的指针
  • key: 并不直接用字符串存储,使用sds结构
  • value: 都使用redisObject结构,可以绑定不同类型,如string,set,zset,hash,list
  • jemalloc: 所有对象都需要使用分配器分配内存。

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;
} robj;
  • type: 对象的类型,如REDIS_STRING,REDIS_REDIS_LIST,REDIS_REDIS_HASH,REDIS_REDIS_SET, REDIS_REDIS_ZSET
  • encoding: 对象的内部编码,占4个字节
  • lru: 对象最后一次被程序访问的时间。volatile-lru或allkeys—lru中,优先释放空转时间最长的对象。
  • refcount: 记录该对象被引用的次数,类型为整型。
    • Redis中被多次引用的对象,成为共享对象
    • 目前共享对象只支持整形的字符串对象 (CPU和时间的平衡,整形判断相同复杂度O(1),其他类型O(n))
    • 目前redis在初始化时,会创建10000个字符串对象,0~9999
  • Ptr: 指向具体的对象

SDS和C中string的区别

redis没有使用C中以’\0’结尾的字符串数组,而使用了Simple Dynamic String,简单动态字符串.

struct sdshdr {
    int len;  // buf已使用的长度
    int free; // buf未使用的长度
    char buf[]; // 字节数组
};

优越性:

  1. 获取字符串长度
  2. 杜绝缓冲区溢出,减少修改字符串时带来的内存重分配次数
  3. 可存取二进制数据。C字符串以空字符串作为字符串结束的标志,而对于一些二进制的文件,内容可能包括空字符串,因此C字符串不能正确存储。而sds会记录数据长度,所以可以避免。