具有到期的缓存的最优算法

时间:2013-09-13 07:24:46

标签: python performance algorithm caching

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

  1. 最多数百万个小物件(平均100个字节)
  2. 速度是关键(放置和获取),我希望操作时间在几微秒
  3. 只有一个线程访问它 - 所以它可以只在内存中(不需要持久性)
  4. 键是MD5哈希(如果重要)
  5. 有一个到期时间,缓存的全局 - 每个密钥应在到期时间后从缓存中删除,从第一次放置的时间算起
  6. 现在,重点是如何实现过期 - 因为其他一切都可以使用简单的字典来完成。最简单的解决方案 - 定期迭代所有数据并删除过期的密钥 - 可能会锁定整个缓存太长时间。可以通过在每次清理过程中迭代部分数据来改进它 - 但仍然需要一些时间(或者不会足够快地清理它)。同时逐个删除密钥看起来像浪费CPU - 因为它们可以批量删除(不必在到期后立即删除 - 我们可以提供一些额外的RAM来保持过期的密钥更长一点)。

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

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

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

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

3 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:0)

哈希表的一个实现是为每个哈希值存储(键,值)列表。您可以将其扩展为存储每个哈希值的(键,插入时间,值)列表。在获取和设置时,您可以在扫描您感兴趣的密钥时丢弃过期的项目。

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

这种方法的良好属性是没有进行并发清理,并且开销或多或少不变。

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

答案 2 :(得分:-1)

使用在N秒后触发事件的定时器服务(用Python编写?)。对于每个关键计划,一个计时器事件(它们非常轻量级)并让它删除密钥。

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