技术开发 频道

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

  提一下string常见的优化方法

       尽量使value为纯数字

  这样字符串会转化成int类型减少内存的使用.

redis.c
=========
37 void setCommand(redisClient *c) {
38   c->argv[2] = tryObjectEncoding(c->argv[2]);
39   setGenericCommand(c,0,c->argv[1],c->argv[2],NULL);
40 }
object.c
=======
275   o->encoding = REDIS_ENCODING_INT;
276   sdsfree(o->ptr);
277   o->ptr = (void*) value;

 

  可以看到sds被释放了,数字被存储在指针位上,所以对于set hello 1111111就只需要48字节的内存.

  调整REDIS_SHARED_INTEGERS

  如果value数字小于宏REDIS_SHARED_INTEGERS(默认10000),则这个redisObject也都节省了,使用redis Server启动时的share Object.

object.c
=======
269 if (server.maxmemory == 0 && value >= 0 && value < REDIS_SHARED_INTEGERS &&
270   pthread_equal(pthread_self(),server.mainthread)) {
271   decrRefCount(o);
272   incrRefCount(shared.integers[value]);
273   return shared.integers[value];
274 }

   这样一个set hello 111就只需要32字节,连redisObject也省了.所以对于value都是小数字的应用,适当调大REDIS_SHARED_INTEGERS这个宏可以很好的节约内存.

  出去kv之外,dict的bucket逐渐变大也需要消耗内存,bucket的元素是个指针(dictEntry**), 而bucket的大小是超过key个数向上求整的2的n次方,对于1w个key如果rehash过后就需要16384个bucket.

  开始string类型的容量预估测试, 脚本如下

#! /bin/bash

redis
-cli info|grep used_memory:

for (( start = 10000; start < 30000; start++ ))
do
    redis
-cli set a$start baaaaaaaa$start > /dev/null
done

redis
-cli info|grep used_memory:

   根据上面的总结我们得出string公式

  string类型的内存大小 = 键值个数 * (dictEntry大小 + redisObject大小 + 包含key的sds大小 + 包含value的sds大小) + bucket个数 * 4

  下面是我们的预估值

>>> 20000 * (16 + 16 + 16 + 32) + 32768 * 4
1731072

   运行一下测试脚本

hoterran@~/Projects/redis-2.4.1$ bash redis-mem-test.sh
used_memory:
564352
used_memory:
2295424

  计算一下差值

>>> 2295424 - 564352
1731072

  都是1731072,说明预估非常的准确, ^_^

0
相关文章