【问题标题】:Optimal algorithm for cache with expire [closed]过期缓存的最佳算法[关闭]
【发布时间】:2013-09-17 19:16:57
【问题描述】:

我需要简单的缓存结构(在python中,但这并不重要),有一些特定的要求:

  1. 多达数百万个小对象(平均 100 字节)
  2. 速度是关键(put 和 get),我预计操作时间大约为几微秒
  3. 只有一个线程访问它 - 所以它可以只在内存中(不需要持久性)
  4. 键是 MD5 哈希(如果重要的话)
  5. 缓存有一个全局的过期时间 - 每个键都应在过期时间后从缓存中删除,从第一次放入的时间开始计数

现在,重点是如何实现过期 - 因为其他所有事情都可以使用简单的字典来完成。最简单的解决方案 - 定期迭代所有数据并删除过期密钥 - 可能会锁定整个缓存太长时间。可以通过在每个清理过程中迭代部分数据来改进它 - 但仍然需要一些时间(或者清理速度不够快)。也一个一个地删除密钥看起来像 CPU 的浪费 - 因为它们可以分批删除(不必在过期后立即删除 - 我们可以提供一些额外的 RAM 来将过期的密钥保留更长时间)。

在检索期间检查密钥是不够的(尽管应该这样做,以不返回过期的密钥) - 因为许多密钥永远无法检索,然后它们将永远保留(或太久)。

该问题的大多数答案建议使用 memcached,但我认为这会浪费 CPU,特别是当我保留可以通过引用放入字典的对象时,但使用 memcached,它们必须被(反)序列化.

我知道如何实现这一点:将数据分成时间片,实际上有几个字典 - 例如,如果过期时间是 60 秒,那么我们(最多)有 4 个字典,每 20 秒我们添加一个新字典- 放置新密钥的位置,并删除第 4 个 - 我们将在 60 秒前添加密钥。这使得清理速度非常快,但以检索时间为代价,您需要在 4 个字典而不是一个字典中进行查找(并且 RAM 使用量增加了 33%)。

所以最后的问题是:有没有更好的解决方案?或者也许我错了,一些提到的解决方案(一个一个地删除键)会更好更快?我不想重新发明轮子,但在网上没有找到任何好的解决方案。

【问题讨论】:

    标签: python performance algorithm caching


    【解决方案1】:

    只有实验才能告诉你哪个更好。

    这是另一个需要考虑的简单想法:按到达顺序链接链表中的所有键。每次检索键时,从列表的开头进行迭代,并从列表和字典中删除所有过期的项目。

    【讨论】:

    • 你说得对,我应该只是试验一下。已经检查过从 4 个字典中按顺序检索仍然适合 1us 以下,所以这可能是要走的路。但仍然想知道是否有人已经创造了类似的东西。
    【解决方案2】:

    哈希表的一种实现是为每个哈希值存储一个(键,值)列表。您可以将此扩展为存储每个哈希值的(键、插入时间、值)列表。在 get 和 set 上,您都可以在扫描感兴趣的密钥时丢弃过期的项目。

    是的,它可能会在哈希表中保留任意长的过期项目,但平均只有 O(N) 个项目,其中 N 是哈希表的大小。

    这种方法的优点是不会进行并发清理,而且开销或多或少是恒定的。

    如果您关心速度,则必须用 C 而不是 Python 编写代码。

    【讨论】:

      【解决方案3】:

      使用在 N 秒后触发事件的 Timer 服务(在 Python 中安排?)。为每个键安排一个计时器事件(它们非常轻量级)并让它删除键。

      Java 对应的是:http://docs.oracle.com/javase/7/docs/api/java/util/Timer.html

      【讨论】:

      • 正如我所提到的 - 这是一个线程,添加另一个线程来删除密钥会带来很多同步问题 - 而且,这比简单地按顺序处理它们并一个一个地删除要糟糕得多.
      • 一般来说,轮询的效率远低于通知。在这种情况下,您不仅要轮询一个对象的到期时间,还要轮询整个人口。祝你好运!
      • 并且您可以使用定时器通知而不同步缓存本身。只需让它将通知排入队列,并偶尔让您的单个线程耗尽队列并从队列中删除通知对象。我看不出定期检查 1,000,000 个对象以找到 1,000 个过期对象比处理队列中的 1,000 个删除更有效。叹息……
      猜你喜欢
      • 2011-06-29
      • 1970-01-01
      • 1970-01-01
      • 2016-08-28
      • 1970-01-01
      • 2020-08-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多