【问题标题】:Memcached eviction prior to key expiry?密钥到期之前的 Memcached 驱逐?
【发布时间】:2011-10-15 15:28:33
【问题描述】:

如果仍有可用空间,存储在 memcached 中的键/值对是否可以在到期前被驱逐?

我有一个 memcached 进程正在运行,最多允许消耗 6GB;报告使用了 2.5GB,而且这个数字波动很小(一天内 +/- 100MB)。如果我设置一个在 15 分钟内到期的简单字符串值,它是否有可能在 15 分钟过去之前被驱逐(cache.get 返回未找到)?

谢谢, -埃里克

【问题讨论】:

  • 我认为最新的memcache 1.4.36通过slab重新分配解决了这个问题,你可以检查升级memcache实例。顺便问一下,您使用的是哪个版本?

标签: memcached


【解决方案1】:

是的

基本上,memcache 按块分配空间而不是按需分配空间,然后将项目存储到块中并手动管理该内存。因此,与按项目分配空间相比,较小的项目可以“使用”大得多的内存。

这个链接比我能解释得更好

https://groups.google.com/group/memcached/browse_thread/thread/8f460034418262e7?pli=1

编辑:添加更多解释

Memcache 通过分配各种大小的slab 来工作。这些板有许多特定尺寸的槽(由板的类别决定)。

假设(并且仅使用我对 Memcache 内部的抽象),假设最小尺寸的 slab 类是 1K。这意味着最小的插槽是 1K。此外,Memcache 一次只会分配 1024 组,即 1MB 内存。假设我们有这样的配置,我们想将一个 1 字节的对象(char 值?)存储到 Memcache 中。假设这需要 5 个字节的内存(4 个字节的密钥?)。在空缓存中,Memcache 将分配一个可以容纳该值的最小尺寸的新平板(1K 个插槽)。因此,存储 5 个字节将导致 Memcache 分配 1MB 内存。

现在,假设你有很多这样的东西。下一个 1023 将是“空闲的”——Memcache 已经分配了内存,因此不需要额外的内存。最后,您存储了 1024 * 5 字节 = ~5KB,但 Memcache 使用了 1MB 来存储它。存储几百万个这样的数据,您可以想象要消耗千兆字节的内存来存储千字节的数据。

这接近于最坏的情况。实际上,如果需要,可以将 Memcache 配置为具有非常小的最小slab 类大小,并且可以扩大或缩小增长因子(slab 类之间的大小差异)。如果您正在缓存数据库查询,您的项目大小可能从几个字节到几个 KB,页面内容甚至可以达到 MB。

这是关键点Memcache 不会回收内存或清理slab(新版本现在确实有这个功能,因为它对性能有很大影响,但传统上,这就是Memcache 的工作方式)。

假设您的系统已经愉快地运行和缓存了几天。您有数百个不同尺寸的板。您在不重置缓存的情况下将新的页面缓存策略部署到您的应用程序。现在不是缓存整个页面,而是缓存页面的一部分。您已将缓存模式从存储大量 ~1MB 对象更改为存储大量 ~10KB 对象。这就是我们遇到麻烦的地方。 Memcache 分配了一堆保存大约 1MB 对象的平板。您以前从未缓存过许多 10KB 的对象。有 10KB 插槽的slab 很快就被填满了,但是现在你有一大堆已分配的slab,其中包含1MB 的对象,这些对象没有被使用(没有其他东西那么大)。 Memcache 不会将您的 10KB 对象放入 1MB 插槽中(即使这样做了,也不会在很长时间内发挥作用)。它需要获得更多容纳 10KB 对象的slab,但它不能,因为您所有的内存都已分配给容纳 1MB 对象的slab。结果是您可能会在slab 中分配千兆字节的内存来保存1MB 的对象,这些对象在您的10KB 槽slab 已满时处于空闲状态。在这种情况下,尽管有 GB 空闲,您仍将开始从 10KB 插槽平板中逐出项目。

这是一个冗长的、做作的、极端的例子。您的缓存策略很少会发生如此明显或如此显着的变化。 slab-classes 的默认增长因子是 1.25,因此您将拥有具有 1KB 插槽、1.25KB 插槽、1.5KB 插槽等的slab。这个概念成立——如果您大量使用特定大小的slab 并且模式发生变化(sql查询返回更多对象?网页变大?在表格中添加一列,将缓存的响应向上移动到一个平板类?等等)然后你会得到一堆“错误”大小的平板,你可以拥有尽管有千兆字节的“未使用”空间,但“无处”存储东西。

如果您被驱逐,可以通过 telnet 进入 Memcache 并找出导致驱逐的平板。通常,缓存重置(是的,清空所有内容)可以解决问题。这是有关如何获取统计信息的参考。 http://lzone.de/articles/memcached.htm

【讨论】:

  • 虽然这在理论上可以回答这个问题,it would be preferable 在此处包含答案的基本部分,并提供链接以供参考。
  • 应该采用什么策略来最小化楼板?将数据填充到常见大小会帮助还是使情况变得更糟?设置slab大小的命令是什么?
  • 绝对不要垫。充其量,这无济于事,更糟糕的是,如果您计算错误,情况会变得更糟。平板配置是在命令行上设置的。 -n 是最小空间,-f 是增长因子(平板之间的增量)。这是一个示例链接:dom.as/2008/12/25/memcached-for-small-objects
  • @JohnHinnegan,我正在关注您的回答。发现,memcache 现在支持slab_reassign,这里是发布说明github.com/memcached/memcached/wiki/ReleaseNotes1425 和对此的PR - github.com/memcached/memcached/pull/113
  • @ArindamNayak 你测试了吗?当我写那个答案时,存在一个版本。从日期来看,您链接到的内容看起来更新。无论如何,当我们测试时,我们发现启用该功能会导致非常显着的性能损失。我们处于对延迟非常敏感的环境中,所以这是不可接受的。 YMMV
【解决方案2】:

Memcached 根据不同内存块的slab存储数据。如果已经分配了不同的内存块,那么最近最少使用算法在该slab上运行并将数据逐出,即使其他内存slab中没有数据。

因此,数据大小的大分布可能是造成此问题的原因。通过运行多个 memcached 实例并将其用作分布式系统,可以减少问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-15
    • 2014-12-12
    • 2014-02-15
    • 1970-01-01
    相关资源
    最近更新 更多