9

由于 Redis 尝试将字符串解析为 64 位有符号整数,存储 32 位有符号整数的二进制表示而不是基数 10 整数字符串是一个好主意吗?

在我们的系统中,我们有许多 32 位有符号整数 ID 的列表。

I can store them like
lpush mykey 102450  --> redis cast 102450 to 8 bytes long

or store it like 
lpush mykey  \x00\x01\x19\x32  ---> this is just 4 bytes
4

2 回答 2

19

在内部,Redis 以最有效的方式存储字符串。将整数强制转换为 radix 10 字符串实际上会占用更多内存。

这是 Redis 存储字符串的方式 -

  1. 小于 10000 的整数存储在共享内存池中,并且没有任何内存开销。如果您愿意,可以通过更改redis.h 中的常量 REDIS_SHARED_INTEGERS并重新编译 Redis 来增加此限制。
  2. 大于 10000 且在 long 范围内的整数占用 8 个字节。
  3. 常规字符串采用 len(string) + 4 个字节作为长度 + 4 个字节用于标记可用空间 + 1 个字节作为空终止符 + 8 个字节作为 malloc 开销。

在您引用的示例中,它的问题是 8 个字节的长字符串和 21 个字节的字符串。

编辑 :

因此,如果我有一组数字都小于 10,000,Redis 如何存储我的集合?

这取决于你有多少元素。

如果您的集合中的元素少于 512 个(请参阅set-max-intset-entries参考资料),那么该集合将存储为一个 IntSet。IntSet 是有序整数数组的美名。由于您的数字小于 10000,因此每个元素将使用 16 位。它(几乎)与 C 数组一样具有内存效率。

如果您有超过 512 个元素,则该集合将成为一个 HashTable。集合中的每个元素都包装在一个名为 的结构中robj,该结构具有 16 个字节的开销。该robj结构有一个指向共享整数池的指针,因此您无需为整数本身支付任何额外费用。最后,robj实例存储在哈希表中,哈希表的开销与集合的大小成正比。

如果您对某个元素究竟消耗了多少内存感兴趣,请在您的数据集上运行redis-rdb-tools(免责声明:我是该工具的作者)。或者你可以阅读MemoryCallback类的源代码,注释解释了内存是如何布局的。

于 2013-04-22T04:17:23.557 回答
1

字符串是按长度存储的,所以它在数据库中不仅仅是 4 个字节——它可能存储为 4 个字节数据 + 4 个字节长度 + 填充,所以你什么也得不到。

于 2013-04-22T01:05:17.847 回答