Redis内存优化

时间:2011-09-18 22:25:46

标签: python optimization redis

我试图在Redis端以非常高效的内存方式编码一些数据(实际上是一个非常大的字符串)。据Redis文档称,它声称“尽可能使用散列”,它声明了两个配置参数:

  • “hash-max-zipmap-entries”,如果我理解的话它表示每个哈希键最多必须有多少个键(我是对的吗?)。

  • “hash-max-zipmap-value”,表示值的最大长度。它实际上是指领域还是价值?长度是以字节,字符还是什么?

我的想法是将字符串(以某种方式具有固定长度)分割成与上述参数一致的数量,并将它们存储为值。字段应该只是序列号,以确保一致的解码..

编辑:我已经进行了广泛的基准测试,似乎在哈希中对字符串进行编码会使内存消耗量提高约50%。

这是我的基准测试脚本:

import redis, random, sys

def new_db():
    db = redis.Redis(host='localhost', port=6666, db=0)
    db.flushall()
    return db

def db_info(db):
    return " used memory %s " % db.info()["used_memory_human"]

def random_string(_len):
    letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
    return "".join([letters[random.randint(0,len(letters)-1)] for i in range(_len) ]) 

def chunk(astr, size):
    while len(astr) > size:
        yield astr[:size]
        astr = astr[size:]
    if len(astr):  
        yield astr 

def encode_as_dict(astr, size): 
    dod={}
    cnt = 0
    for i in chunk(astr,size):
        dod[cnt] = i
        cnt+=1
    return dod


db=new_db()
r = random_string(1000000)
print "size of string in bytes ", sys.getsizeof(r)
print "default Redis memory consumption", db_info(db)
dict_chunk = 10000

print "*"*100
print "BENCHMARKING \n"

db=new_db()
db.set("akey", r)
print "as string " , db_info(db)
print "*"*100

db=new_db()
db.hmset("akey", encode_as_dict(r,dict_chunk))
print "as dict and stored at value" , db_info(db)
print "*"*100

和我的机器上的结果(32位Redis实例):

size of string in bytes  1000024
default Redis memory consumption  used memory 534.52K 
******************************************************************************************
BENCHMARKING 

as string   used memory 2.98M 
******************************************************************************************
as dict and stored at value  used memory 1.49M 

我想通过玩我提到的参数,是否有更有效的方法将字符串存储为哈希。所以首先,我必须意识到他们的意思..然后我会再次进行基准测试,看看是否有更多的收益..

EDIT2:我是白痴吗?基准测试是正确的,但确认了一个大字符串。如果我重复许多大字符串,将它们存储为大字符串是肯定的赢家..我认为我得到一个字符串的结果的原因在于Redis内部..

4 个答案:

答案 0 :(得分:6)

实际上,存储大字符串的最有效方法是作为一个大字符串 - 其他任何东西都会增加开销。你提到的优化是为了处理很多短字符串,字符串之间的空格可能成为一个问题。

存储大字符串的性能可能不如小字符串好,因为需要找到更多的连续块来存储它,但这实际上不太可能影响任何东西。

答案 1 :(得分:4)

我已经尝试过阅读Redis文档,了解您提到的设置,这并不容易。但这听起来并不像我的计划是个好主意。他们描述的散列旨在为小值节省内存。这些值仍然完全存储在内存中。这听起来像他们在多次出现时减少了开销,例如,当字符串被添加到多个集合时。您的字符串不符合这些条件。我强烈怀疑你会使用你的方案来节省内存。

您当然可以对其进行基准测试。

答案 2 :(得分:2)

尝试查看Redis Memory Usage文章,您可以在其中找到各种数据类型及其内存消耗的良好比较。

答案 3 :(得分:0)

当您在散列中存储数据时,每个值开销只会跳过~100个字节!

因此,当您的字符串长度相当时,例如100-200字节,比您可以看到30-50%的内存节省,对于整数而言,它的内存减少了10倍!

以下是几个链接:

About 100 bytes overhead

Different memory optimization comparision gist