技术开发 频道

Redis数据库:内存容量的预估和优化

  【IT168技术】Redis是个内存全集的kv数据库,不存在部分数据在磁盘部分数据在内存里的情况,所以提前预估和节约内存非常重要.本文将以最常用的string和zipmap两类数据结构在jemalloc内存分配器下的内存容量预估和节约内存的方法.

  先说说jemalloc,传说中解决firefox内存问题freebsd的默认malloc分配器,area,thread-cache功能和tmalloc非常的相识.在2.4版本被Redis引入,在antirez的博文中提到内节约30%的内存使用.相比glibc的malloc需要在每个内存外附加一个额外的4字节内存块,jemalloc可以通过je_malloc_usable_size函数获得指针实际指向的内存大小,这样Redis里的每个key或者value都可以节约4个字节,不少阿.

  下面是jemalloc size class categories,左边是用户申请内存范围,右边是实际申请的内存大小.这张表后面会用到.

1     - 4     size class:4
5     - 8     size class:8
9     - 16    size class:16
17    - 32    size class:32
33    - 48    size class:48
49    - 64    size class:64
65    - 80    size class:80
81    - 96    size class:96
97    - 112   size class:112
113   - 128   size class:128
129   - 192   size class:192
193   - 256   size class:256
257   - 320   size class:320
321   - 384   size class:384
385   - 448   size class:448
449   - 512   size class:512
513   - 768   size class:768
769   - 1024  size class:1024
1025  - 1280  size class:1280
1281  - 1536  size class:1536
1537  - 1792  size class:1792
1793  - 2048  size class:2048
2049  - 2304  size class:2304
2305  - 2560  size class:2560

  string

  string类型看似简单,但还是有几个可优化的点.先来看一个简单的set命令所添加的数据结构.

Redis数据库:内存容量的预估和优化

  一个set hello world命令最终(中间会malloc,free的我们不考虑)会产生4个对象,一个dictEntry(12字节),一个sds用于存储key,还有一个redisObject(12字节),还有一个存储string的sds.sds对象除了包含字符串本生之外,还有一个sds header和额外的一个字节作为字符串结尾共9个字节.

sds.c
========
51 sds sdsnewlen(const void *init, size_t initlen) {
52     struct sdshdr *sh;
53
54     sh = zmalloc(sizeof(struct sdshdr)+initlen+1);

sds.h
=======
39 struct sdshdr {
40     int len;
41     int free;
42     char buf[];
43
};

  根据jemalloc size class那张表,这个命令最终申请的内存为16(dictEtnry) + 16 (redisObject) + 16(“hello”) + 16(“world”),一共64字节.注意如果key或者value的字符串长度+9字节超过16字节,则实际申请的内存大小32字节.

0
相关文章