Redis知识总结--string的内部实现

SDS(Simple Dynamic String)

String的数据结构是一个字节数组,但简单的获取数组长度的时间复杂度就是O(n),这对于单线程的redis来讲是不能接受的,因此string在redis中的实现是SDS类,SDS类的结构总体如下(C已忘,只能用java大致表达下):

public class SDS {
  // string内容的真实长度,为了节约内存,这里是个泛型
  // 当内容较少时,使用byte或short
  private T length;
  // 为string分配的内存空间大小,同样为了节约内存,用了泛型
  private T capacity;
  // string的真实内容,使用字节数组存储
  private byte[] content;
  // 特殊标记,不知道干嘛的
  private byte flags;
}

如上,长度直接保存下来了--虽然两者没什么关联,但我想到了mysql的Myisam引擎,也是直接将表的数据条数直接保存下来--这样要获取长度直接取值即可;

embded 和 RAW

使用debug object命令会发现,不同长度的string的encoding有embed和raw两种类型,也是为了节省空间,64字节及以下的string会使用embed存储,以上使用RAW存储(不同redis版本下可能会有不同的界限),之所以使用64为界是因为内存分配函数malloc等都是一次分配2的若干次幂大小的内存,另外即使分配64字节给string使用,content也只有44字节的内存可以存储,原因正是因为下面的redis头对象也占了坑

RedisObject

public class RedisObject {
  // 数据类型,只使用4bit
  private int4 type;
  // 数据的encoding类型,只使用4bit
  private int4 encoding;
  // 数据的lru信息,只使用24bit
  private int24 lru;
  // 该数据的引用计数,使用32bit
  private int32 refcount;
  // 这是个指针,指向数据对象,在64位操作系统下,使用8个字节
  private Poniter *p;
}

可以发现,对象头至少使用16个字节,而假使SDS的三个辅助属性都只使用1字节的话,content也就只剩下64-19=45字节的空间可以使用了,还有一个字节用来保存字符串的结尾字符,这个字符通常使用的是null,而在redis中使用的是\0,\0使用了1个字节,content的可用有效字符就仅剩44字节了

猜你喜欢

转载自my.oschina.net/u/580449/blog/2249504