redis减少了20-50个字符长度的字符串键的内存消耗



我有一个键,它是由许多不同的元素连接而成的

[15000个唯一字符串]+[:]+[5个唯一字符串]+[:]+[1或0]+[:]+[15000个独特字符串]+[:]+[1或0]=长度在20到50个字符之间的字符串(例如:温哥华:临时:1:Kelowna:高:0)

根据我的计算,将有大约10亿个组合,每个组合都将是一个关键。阅读redis文档(http://redis.io/topics/memory-optimization)他们建议您散列密钥:例如,"object:11558960"=>"1"可以变成"object:1155"8960">>"1"。

我正在考虑应用内存优化的最佳方法。我的第一个想法是为字符串创建一个数字表示。所以我会使用MySQL并创建查找表,其中每个字符串都有一个相应的数字整数。通过这种方式,我可以更恰当地散列,因为我可以更容易地划分数字,而不是字符串。同样,数字会产生更短的键,我认为这会节省内存。这里的问题是10亿个密钥,这是MySQL的大量开销,因为我必须创建联接等等。

我读到的另一个解决方案是,在插入redis之前,先获取我创建的字符串,然后使用php的gzcompres之类的东西对其进行压缩。(http://labs.octivi.com/how-we-cut-down-memory-usage-by-82/)。

有没有什么最佳实践优化可以用来降低redis内存消耗,因为目前它仍然太高了?为了节省更多内存,我愿意放弃CPU的电源。我的值只能是0-50之间的一位数或两位数整数。

查找表完全用完了,甚至不用麻烦。哈希解决方案似乎非常适合您的需求。你会希望你的密钥在15000次独特的刺痛之前被分开,给你足够的哈希密钥,让它值得付出努力。

所以不是:

SET Vancouver:temp:1:Kelowna:high:0 10

你会使用

HSET Vancouver:temp:1 Kelowna:high:0 10

现在,第一个[1或0]之后的所有内容都将是一个哈希密钥,因此每个哈希大约有150000个可能的密钥。

我对你的总密钥空间的计算与你的有所不同:

15000 * 5 * 2 * 15000 * 5 * 2 == 22500000000 (22.5 billion)

因此,通过这种方式,您将有150000个可能的密钥(redis密钥),每个密钥有150000个哈希密钥。

redis键和哈希键之间的间隔越左,哈希键的数字偏移就越大。例如,如果你像一样把它分解

HSET Vancouver:temp 1:Kelowna:high:0 10

然后,您将有75000个redis密钥用于哈希,每个哈希可能包含300000个密钥/值对。


另一种方法是使用整数值作为键。如果您的两组15000个唯一字符串和5个唯一字符串中的每一个都有整数映射,那么您可以使用总共34位来表示任何键。例如

 0000000000000   000   0   0000000000000   000   0
|      13     | | 3 | |1| |     13      | | 3 | |1|

13位的范围为0-16383(涵盖所需的1-15000)3位为您提供0-7的范围(包括所需的1-5)1位为您提供所需的二进制1或0范围。

因此,假设这些虚构的值:Vancuver==9987温度==3Kelowna==3454高=2

你会有:

(9987 << 21) + (3 << 18) + (1 << 17) + (3454 << 4) + (2 << 1) + (0 << 0)
==
20945229796

要从给定的密钥中获取值,您只需比特移位并屏蔽

20945229796 >> 20
9987
(20945229796 >> 4) & ((1 << 13) - 1)
3454

下面是一个简单的python脚本,它将值转换为int,并将int转换为值:

values = [9987, 3, 1, 3454, 2, 0]
bits =   [21, 18, 17, 4, 1, 0]
value_and_shift = zip(values, bits)

def key_from_values(values_and_shift):
    return sum(x << y for x, y in value_and_shift)
def extract_values(values_and_shift):
    last_shift = 35
    for value, shift in value_and_shift:
        print "Value should be:", value
        print "Value extracted:", (key >> shift) & ((1 << (last_shift - shift)) - 1)
        print
        last_shift = shift
key = key_from_values(value_and_shift)
print "Using value of:", key
extract_values(value_and_shift) 

输出

Using value of: 20945229796
Value should be: 9987
Value extracted: 9987
Value should be: 3
Value extracted: 3
Value should be: 1
Value extracted: 1
Value should be: 3454
Value extracted: 3454
Value should be: 2
Value extracted: 2
Value should be: 0
Value extracted: 0

最新更新