希望优化Redis内存使用以缓存许多JSON API结果

时间:2012-11-04 19:31:35

标签: c# optimization memory redis servicestack

我是Redis的新手,我只是尝试缓存一些数据,看看内存使用/性能与Memcached等其他选项的比较。我通过IRedisClient

使用ServiceStack.Redis客户端库

我一直在测试Redis,25k键/值对象正在推动250MB内存,带有100MB dump.rdb文件。我需要缓存更多,并且我希望尽可能减少内存消耗。我最好的猜测是每个缓存项的文本(JSON blob)大小约为4k,但如果我的基本数学是正确的,那么至少从内存占用的角度来看,每个项目在Redis中消耗大约10k。转储大小和内存大小之间的巨大差异对我来说有点令人担忧。

我现在也在64位虚拟机上运行,​​据我所知,与32位相比,浪费了大量额外空间,所以我也会研究它。看起来redis每个指针需要2倍的内存(每个键/值缓存?)。这可能是2.5倍磁盘:内存比率的来源吗?

据我所知,我可以编写代码来处理Redis内外数据的压缩/解压缩,但只是好奇是否有某种方法可以配置客户端库来执行类似于say的操作{ {3}}。

使用模式已经过时,不经常写入和/或批量缓存刷新写入。

无论如何,寻找有关如何为给定内存量获取更多缓存项的任何建议。

2 个答案:

答案 0 :(得分:2)

您需要考虑多个要点。在下文中,我假设您的数据存储在每个包含JSON对象的字符串中。

第一点是存储4 KB JSON对象。由于动态数据结构和指针,Redis的开销与有用数据的大小相比绝对可以忽略不计。如果你有很多非常小的对象(每个键大约80个字节),这个开销会很高,但是对于4 KB的对象,这应该不是问题。

因此使用32位版本(减小指针大小)无济于事。

第二点是内存占用和转储文件大小之间的差异可以通过使用LZF算法压缩转储文件中的事实字符串来轻松解释(并且JSON确实压缩得很好)。内存占用量通常远大于非压缩数据的转储文件大小。

现在,您在数据的实际大小和内存占用量之间看到的差异可能是由于分配器内部碎片造成的。通常,人们只考虑外部碎片(即大多数人通常称为内存碎片的碎片),但在某些情况下,内部碎片也可能代表一个主要的开销。请参阅定义here

在您的情况下,4 KB对象实际上是最糟糕的情况之一。 Redis使用jemalloc分配器,具有well-defined allocation classes。您可以看到4 KB是一个分配类,下一个是8 KB。这意味着如果你的一些对象的权重超过4 KB(包括8字节的Redis字符串开销),则将分配8 KB而不是4 KB,并且将浪费一半的内存。

您可以通过仅存储小于4 KB的对象来轻松检查此点,并计算内存占用量与有用数据的预期大小之间的比率。对大于4 KB的对象重复相同的操作并比较结果。

减少开销的可能解决方案:

  • 客户端压缩。使用任何轻量级压缩算法(LZF,LZO,quicklz,snappy)。如果您可以将大多数对象的大小保持在4 KB以下,它将很有效。

  • 更改内存分配器。 Redis makefile还支持tcmalloc(Google allocator)作为内存分配器。它可以减少这些4 KB对象的内存开销,因为分配类是不同的。

请注意,对于其他内存商店,您也会获得相同的开销。例如,对于memcached,slab分配器的工作是优化内存消耗,并最小化内部和外部碎片。

答案 1 :(得分:1)

我很难理解如何有效地使用Redis。特别是当你来自Memcache(获取/设置)VS Redis(字符串,散列,列表,集合和排序集)时。

您应该阅读有关Redis内存使用情况的文章:http://nosql.mypopescu.com/post/1010844204/redis-memory-usage。旧文章(2010),但仍然很有趣。

我在这里看到两个解决方案:

  • 编译并使用32位实例。转储文件在32位和64位之间兼容,如果需要,您可以稍后切换。

  • 我使用Hashes看起来更好:http://redis.io/topics/memory-optimization。阅读“使用哈希在Redis上抽象一个内存效率非常高的普通键值存储”一节。 ServiceStack.Redis提供RedisClientHash。它应该很容易使用!

希望它可以帮到你!