【问题标题】:How to store few millions of cache and then track down 20 oldest cache如何存储几百万个缓存,然后跟踪 20 个最旧的缓存
【发布时间】:2012-05-03 04:48:44
【问题描述】:

我收到一个面试问题,说我需要存储几百万个缓存,然后我需要跟踪 20 个最旧的缓存,一旦缓存收集的阈值增加,就用下一组最旧的缓存替换 20 个最旧的缓存.

我回答是为它保留一个哈希图,问题又增加了 如果我们想快速访问 hashmap 上的任何元素怎么办? 做,所以我告诉它的地图,所以访问不会花时间,但是 面试官不满意。那么这样的空闲方式应该是什么 场景。

【问题讨论】:

  • 你的面试官似乎在描述一个LRU cache,它似乎没有任何琐碎的实现。应该使有趣的学习...

标签: caching data-structures language-agnostic


【解决方案1】:

queue 非常适合查找和删除最旧的成员。

实现为双向链表的队列在两端都有 O(1) 的插入和删除。

priority queue 有助于为队列中的不同项目赋予不同的权重(例如,重新创建某些队列元素可能比其他元素更昂贵)。

您可以使用哈希映射来保存实际元素并根据哈希键快速找到它们,并使用一个哈希键队列来跟踪缓存元素的年龄。

【讨论】:

  • 这意味着保留一个单独的队列,该队列将保留 Map 的 20 个最旧项目的引用?但是在 Map 中存储数百万条记录是有效的做法
  • 否...有一个队列持有对所有缓存元素的引用。映射在基于散列键查找元素方面非常有效,但对于基于诸如时间戳之类的搜索条件查找元素则非常低效。队列只能保存哈希键...使用队列根据年龄对元素进行入队和出队,并使用哈希图保存实际对象。
【解决方案2】:

通过对队列使用双链表并维护元素的哈希映射,您应该能够创建支持最大大小的缓存(甚至是 LRU 缓存)。这应该会导致对对象的引用被存储 3 次,而不是对象被存储两次,如果你实现了这个,一定要检查这个(避免这种情况的简单方法是只对哈希键进行排队)

检查溢出时,您只需将最后一项从队列中弹出,然后将其从哈希映射中删除

当访问一个项目时,您可以使用哈希映射来查找缓存的项目。然后,如果您正在实现 LRU 缓存,您只需将其从队列中删除并将其添加回开头即可。

通过使用这种结构,插入、更新、读取、删除都将是O(1)

接下来的问题是,面试官会询问项目是否能够具有每个缓存项目的生存时间 (TTL)。为此,您需要有另一个队列来维护按生存时间排序的项目,这里唯一的问题是插入现在变为O(n),因为您必须扫描 TTL 队列并找到过期点,所以您必须决定将 TTL 队列存储为 n 树的内存使用是否值得(从而产生O(log n) 插入时间)。或者您可以将您的 TTL 队列实现为每个 ~1 分钟间隔或类似的存储桶,您仍然会得到 ~O(1) 插入,并且只会稍微降低到期后台进程的性能,但不会大大降低(这是一个后台进程)。

【讨论】:

    猜你喜欢
    • 2018-05-06
    • 2018-11-29
    • 2023-04-07
    • 2020-06-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-02
    • 1970-01-01
    • 2017-06-26
    相关资源
    最近更新 更多