我有一个系统处理已经变成无符号长整数的键(通过将短序列打包成字节串).我想尝试将它们存储在Redis中,我希望尽可能以最佳方式进行.我关心的主要是内存效率.
从玩在线REPL我注意到以下两个是相同的
zadd myset 1.0 "123"
zadd myset 1.0 123
Run Code Online (Sandbox Code Playgroud)
这意味着即使我知道我想存储一个整数,它也必须设置为字符串.我从文档中注意到,密钥只是存储为char*s,而像SETBIT这样的命令表明Redis不反对将字符串视为客户端中的字节串.这暗示了一种unsigned long比它们的字符串表示更有效的存储方式.
将unsigned longs 存储在有序集合中的最佳方法是什么?
Joe*_*Joe 12
感谢Andre的回答.以下是我的发现.
Redis键必须是字符串.如果要传递整数,则必须是某种字符串.对于小的,定义良好的值集,Redis会将字符串解析为整数(如果是1).我的猜测是它会使用这个int来定制它的哈希函数(甚至可以根据值静态地维护哈希表).这适用于较小的值(示例是64个条目的默认值,值最多为512).我将在调查期间测试更大的值.
http://redis.io/topics/memory-optimization
另一种方法是压缩整数,使其看起来像一个字符串.
看起来可以使用任何字节字符串作为键.
对于我的应用程序的情况,它实际上没有存储字符串或整数那么大的差异.我想Redis中的结构无论如何都经历了某种对齐,所以无论如何可能会有一些预先浪费的字节.无论如何都要对值进行哈希处理.
使用Python进行测试,因此我可以使用Python创建值struct.pack.long longs的重量为8个字节,非常大.鉴于整数值的分布,我发现存储字符串实际上是有利的,特别是当以十六进制编码时.
由于redis字符串是"Pascal-style":
struct sdshdr {
long len;
long free;
char buf[];
};
Run Code Online (Sandbox Code Playgroud)
鉴于我们可以在那里存储任何东西,我做了一些额外的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)
Run Code Online (Sandbox Code Playgroud)
这似乎是一个微不足道的挽救(或根本没有).可能是由于Redis中的struct padding.这也驱使Python CPU通过屋顶,使它有点没有吸引力.
我使用的数据是200000 zsets consecutive integer => (weight, random integer) × 100,加上一些倒排索引(基于随机数据).dbsize产生1,200,001个键.
服务器的最终内存使用:1.28 GB RAM,1.32 Virtual.无论如何,各种调整产生的差异不超过10兆字节.
所以我的结论是:
不要将编码麻烦到固定大小的数据类型.如果需要,只需将整数作为字符串存储在十六进制中.它不会产生那么大的差别.
参考文献:
http://docs.python.org/library/struct.html
http://redis.io/topics/internals-sds
| 归档时间: |
|
| 查看次数: |
6690 次 |
| 最近记录: |