Python Redis内存优化

Python Redis内存优化,python,optimization,redis,Python,Optimization,Redis,我试图在Redis端以非常节省内存的方式对一些数据(实际上是一个非常大的字符串)进行编码。根据Redis文档,它声称“在可能的情况下使用哈希”,并声明了两个配置参数: “hash max zipmap entries”,如果我理解得很好,它表示每个hash键最多必须有多少个键(对吗?) “hash max zipmap value”,表示该值的最大长度。它实际上是指字段还是指值?长度单位是字节、字符还是什么 我的想法是将字符串(不知何故具有固定长度)拆分为与上述参数配合良好的数量,并将其存储

我试图在Redis端以非常节省内存的方式对一些数据(实际上是一个非常大的字符串)进行编码。根据Redis文档,它声称“在可能的情况下使用哈希”,并声明了两个配置参数:

  • “hash max zipmap entries”,如果我理解得很好,它表示每个hash键最多必须有多少个键(对吗?)

  • “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实例)上的结果:

我想问的是,是否有一种更有效的方法通过使用我提到的参数将字符串存储为散列。因此,首先,我必须明白他们的意思。。然后我将再次进行基准测试,看看是否有更多的收益


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

我试着阅读了Redis文档中关于您提到的设置的内容,这并不容易。但我觉得你的计划不是个好主意。他们描述的散列是为了为小值节省内存而设计的。这些值仍然完全存储在内存中。在我看来,当它们多次出现时(例如,将一个字符串添加到多个集合中),它们似乎在减少开销。您的字符串不符合这些条件。我强烈怀疑你会用你的计划节省内存


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

试着看看这篇文章,您可以在其中找到各种数据类型及其内存消耗的良好比较。

实际上,存储大字符串的最有效方法是将其作为大字符串—任何其他方法都会增加开销。您提到的优化用于处理大量短字符串,其中字符串之间的空白可能会成为一个问题


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

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

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

以下是几个链接:


如果您谈论的是加密散列,则无法对其进行解码,因为无限多的不同字符串映射到任何给定的散列。加密散列?我只是尝试在Redis散列中高效地存储一个大字符串,方法是在Ai块中拆分它,其中len(Ai)<“hash max zipmap value”。然后我可以使用chunk\u sequence\u number来恢复它,这是保存每个Ai的字段。我对Redis一无所知,但“hash”和“decode”通常意味着有人不了解hash函数是如何工作的。我不知道它是否适用于这种情况。那么好吧:),Redis哈希是一种由键标识的数据结构,具有字段和值。散列是在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