【问题标题】:Optimizing redis sorted set memory usage优化redis排序集内存使用
【发布时间】:2014-04-09 14:31:00
【问题描述】:

我目前在 Redis 中有 22k 个排序集。每个键的格式如下:

monitor:<type>:feed:<MongoId>

这些排序后的集合共有 11895225 个项目。这些集合有一个 unix 时间戳作为分数,一个 MongoId 作为成员。

<timestamp> - <MongoId>

设置非常快,但数据库大小为 1.8g。是否可以进行任何优化来减少内存使用量(请记住,我需要按时间对数据进行排序)?

【问题讨论】:

    标签: sorting database-design memory-management redis sortedset


    【解决方案1】:

    您可以进行一些优化,但不要期望太多。每个成员在数据本身之上有大约 64 字节的开销(成员键 + 分数/浮点数)。

    因此,最小内存大小(不含数据)已经是 0.77GB 左右。

    看到 Didier Spazia 的这个好答案:Redis 10x more memory usage than data

    要进行优化,您可以使用客户端散列和/或客户端压缩。


    关于您的数据设计:

    这些集合有一个 unix 时间戳作为键,一个 MongoId 作为值。

    不太清楚你在这里的意思。 key 是整个排序集的正确术语。您的会员分数是多少,您的会员字符串是多少?您是否依赖按分数排序?而且,还按字符串进行字典排序?如果两者兼而有之:除了可能缩短字符串中的字符串/标记之外,您无能为力。您可以将此与使用 MsgPack 格式序列化数据结合起来。如果字符串中有数字,这很有用,当序列化为 MsgPack 时使用的字节数要少得多。如果您使用数组(而不是序列化的字典),您可以再次保护一些空间。使用 ints/floats,确保您的字节序匹配所需的排序,但当您在成员字符串中使用 MsgPack 并且您需要排序集的字典排序特征时。

    希望这会有所帮助,TW

    【讨论】:

    • 对不起,unix时间戳是分数,mongoid是key的成员。我并没有真正遵循“优化时”的意思。但是我需要按分数排序的列表,我不需要对成员的字符串进行字典排序。
    • 在这种情况下,您可以在客户端压缩成员字符串数据。例如通过使用他LZ4 算法。
    • “优化时”:确实不清楚。我编辑了它。我还稍微澄清了在这种情况下 MsgPack 的使用。
    【解决方案2】:

    除了来自 Tw 和代理 Didier 的出色信息之外,另一个不涉及更改代码的选择是使用 32 位版本的 Redis。当然,如果您预计即使在 32b 机制下数据也会增长到 2GB 以上,这不一定是一个很好的选择。但是,对于“较小”数据集的直接内存大小减少,它可能是一个简单的解决方案。

    在最坏的情况下,您可以使用数据副本进行尝试并对其进行测试,以查看您的边界在哪里以及您减少了多少内存,但一个体面的经验法则大约是一半。

    【讨论】: