redis的embstr编码

问题来了

今天在看书籍《Redis设计与实现》的时候,在8.2字符串对象里面写到

  • 如果字符串对象保存的是一个字符串值, 并且这个字符串值的长度大于 39 字节, 那么字符串对象将使用一个简单动态字符串(SDS)来保存这个字符串值, 并将对象的编码设置为 raw 。
  • 如果字符串对象保存的是一个字符串值, 并且这个字符串值的长度小于等于 39 字节, 那么字符串对象将使用 embstr 编码的方式来保存这个字符串值。

自己本地实验的时候,就算字符小于39,也是raw类型的,不知道为什么。


原来是版本的原因

去查看源码。才发现这个和redis的版本有关系。查看redis-3.0和最新的版本的object.c文件,可以发现在创建StringObject的时候,会和REIDS_ENCODING_EMBSTR_SIZE_LIMIT比较,这个的默认值是39。查看一下redis-2.8版本的源码,并没有发现比较,而是直接创建了。
所以我猜测这个embstr编码是3.0以上版本才出现的。


39哪来的

至于为什么是39,这个讲起来就比较复杂了,我就慢点说。
embstr是一块连续的内存区域,由redisObject和sdshdr组成。其中redisObject占16个字节,当buf内的字符串长度是39时,sdshdr的大小为8+8+39+1=56,那一个字节是'\0'。加起来刚好64。是不是发现了什么?

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;
struct sdshdr {
    unsigned int len;
    unsigned int free;
    char buf[];
};

从2.4版本开始,redis开始使用jemalloc内存分配器。这个比glibc的malloc要好不少,还省内存。在这里可以简单理解,jemalloc会分配8,16,32,64等字节的内存。embstr最小为16+8+8+1=33,所以最小分配64字节。当字符数小于39时,都会分配64字节。
这个默认39就是这样来的

posted @ 2015-08-29 17:07  lhcpig  阅读(6221)  评论(1编辑  收藏  举报