感谢安德烈的回答。这是我的发现。
直接存储整数
Redis 键必须是字符串。如果你想传递一个整数,它必须是某种字符串。对于小的、定义明确的值集,Redis 会将字符串解析为一个整数(如果它是一个整数)。我的猜测是它会使用这个 int 来定制它的哈希函数(或者甚至根据值静态地标注一个哈希表)。这适用于小值(示例是 64 个条目的默认值,最大值为 512)。我会在调查期间测试更大的值。
http://redis.io/topics/memory-optimization
存储为字符串
另一种方法是压缩整数,使其看起来像一个字符串。
看起来可以使用任何字节字符串作为键。
对于我的应用程序来说,存储字符串或整数实际上并没有太大区别。我想Redis中的结构无论如何都会经历某种对齐,所以无论如何可能会有一些预先浪费的字节。在任何情况下,该值都会被散列。
使用 Python 进行测试,因此我能够使用 struct.pack 创建值。 long longs 有 8 个字节,相当大。鉴于整数值的分布,我发现存储字符串实际上可能是有利的,尤其是在以十六进制编码时。
由于 redis 字符串是“Pascal 风格”:
struct sdshdr {
long len;
long free;
char buf[];
};
鉴于我们可以在其中存储任何东西,我做了一些额外的 Python 来将类型编码为尽可能短的类型:
def do_pack(prefix, number):
"""
Pack the number into the best possible string. With a prefix char.
"""
# char
if number < (1 << 8*1):
return pack("!cB", prefix, number)
# ushort
elif number < (1 << 8*2):
return pack("!cH", prefix, number)
# uint
elif number < (1 << 8*4):
return pack("!cI", prefix, number)
# ulonglong
elif number < (1 << 8*8):
return pack("!cQ", prefix, number)
这似乎节省了微不足道的费用(或根本没有节省)。可能是由于 Redis 中的结构填充。这也将 Python CPU 推到了顶峰,使其有点缺乏吸引力。
我使用的数据是 consecutive integer => (weight, random integer) × 100 的 200000 个 zset,加上一些倒排索引(基于随机数据)。 dbsize 产生 1,200,001 个密钥。
服务器的最终内存使用:1.28 GB RAM,1.32 虚拟。各种调整所产生的差异不超过 10 兆字节。
所以我的结论是:
不要费心编码成固定大小的数据类型。只需将整数存储为字符串,如果需要,可以使用十六进制。不会有太大的不同。
参考资料:
http://docs.python.org/library/struct.html
http://redis.io/topics/internals-sds