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

时间:2014-09-15 23:29:14

标签: redis

我有一个通过汇总来自许多不同元素生成的密钥。:

[15,000个独特字符串] + [:] + [5个唯一字符串] + [:] + [1或0] + [:] + [15,000个唯一字符串] + [:] + [5个唯一字符串] + [ :] + [1或0] =长度在20到50个字符之间的字符串(例如:温哥华:温度:1:基洛纳:高:0)

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

我正在考虑应用内存优化的最佳方法。我的第一个想法是为字符串创建一个数字表示。所以我会使用MySQL并创建查找表,其中每个字符串都有一个相应的数字整数。这样我可以更加适当地散列,因为我可以更轻松地分割数字,然后我可以使用String。同样,数字会创建更短的密钥,我认为这会节省内存。这里的问题是10亿个密钥,这是MySQL的大量开销,因为我必须创建连接和所有这些。

我读到的另一个解决方案是接受我创建的字符串,然后在插入redis之前使用php&#g; gzcompres之类的东西压缩它。 (http://labs.octivi.com/how-we-cut-down-memory-usage-by-82/)。

我是否可以使用最佳实践优化来降低我的redis内存消耗,因为它目前仍然太高?我愿意放弃CPU电源以节省更多内存。我的值只是0-50的单位或双位整数。

1 个答案:

答案 0 :(得分:3)

查找表完全没问题,甚至没有打扰。哈希解决方案似乎很适合您的需求。你希望你的密钥在15,000个独特的stings之前分开,为你提供足够的哈希密钥,使其值得付出努力。

所以而不是:

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

你会用

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

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

我对你的总密钥空间的计算与你的有关:

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

所以这样做你将拥有150,000个可能的密钥(redis密钥),每个密钥有150,000个可能的哈希密钥。

在redis键和散列键之间的中断越远,散列键的数字越倾斜。例如,如果您将其分解为

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

然后你会有75,000个redis密钥用于散列,每个散列可能包含300,000个键/值对。


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

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

13位给你的范围是0-16383(涵盖了所需的1-15,000) 3位为您提供0-7范围(涵盖所需的1-5) 1位为您提供所需的二进制1或0范围。

所以假设这些价值: Vancuver == 9,987 temp == 3 基洛纳== 3,454 高= 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