2

我是 Redis 的新手,我只是在尝试缓存一些数据,看看内存使用/性能与 Memcached 等其他选项相比如何。我通过IRedisClient使用 ServiceStack.Redis 客户端库

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

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

我知道我可以自己编写代码来处理进出 Redis 的数据压缩/解压缩,但只是好奇是否有某种方法可以配置客户端库以执行与说StreamExtensions类似的操作。

使用模式很重,写入不频繁,和/或批量缓存刷新写入。

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

4

2 回答 2

2

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

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

所以使用 32 位版本(减少指针的大小)将无济于事。

第二点是内存占用和转储文件大小之间的差异很容易解释为转储文件中的字符串是使用 LZF 算法压缩的(JSON 确实压缩得很好)。内存占用量通常比非压缩数据的转储文件大小大得多。

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

在您的情况下,4 KB 对象实际上是最坏的情况之一。Redis 使用 jemalloc 分配器,具有明确定义的分配类。您可以看到 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 分配器的工作是优化内存消耗,并最大限度地减少内部和外部碎片。

于 2012-11-05T09:07:07.073 回答
1

我很难理解如何有效地使用 Redis。特别是当您来自 Memcache(get/set) VS Redis(字符串、哈希、列表、集合和排序集)时。

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

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

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

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

希望它可以帮助你!

于 2012-11-04T22:01:50.920 回答