【问题标题】:Cache with timeout using .Net 4 & Concurrent Collections使用 .Net 4 和并发集合进行超时缓存
【发布时间】:2011-03-09 11:56:33
【问题描述】:

您将如何使用 .Net 4 的新并发集合实现支持超时的缓存类?

缓存类通常包含数十万个条目。很大一部分缓存可能同时过期。

与可能因内存压力而缩小的典型 Web 缓存不同,此类应仅在对象超时时自动删除。

【问题讨论】:

    标签: .net multithreading caching concurrency .net-4.0


    【解决方案1】:

    为什么需要实现自定义缓存类?默认实现还不够吗?有一个whole new assembly dedicated to caching in .NET 4.0。缓存值 10 分钟的示例:

    var cache = MemoryCache.Default;
    cache.Add("key", new object(), DateTime.Now.AddMinutes(10));
    

    【讨论】:

    • 嗨达林,感谢您的回复。这个问题被认为是一个挑战。尽管它的灵感来自一个实际问题,但我实际上并不打算实现缓存。事实上,我对“缓存”一词的选择是不幸的。我感兴趣的是带有超时的字典。只要没有超时,字典在任何情况下都不能清除条目。我修改了问题以澄清这一点。 MemoryCache,虽然是一个有用的工具,但由于内存压力而清除对象。这使得它不适合我的假设场景。
    • @Teleo,感谢您的澄清。您绝对正确,MemoryCache 将由于内存压力而被清除。
    【解决方案2】:

    退后一步,考虑一下基于大小的缓存是如何工作的。 LRU 策略将删除最近使用的条目。当一个条目被访问(读取)或变异(写入)时,它被认为是被使用的。最常见的算法是让一个双向链表横切哈希表,以便表查找在 O(1) 时间内找到列表链中的条目。该列表保持顺序,其中头部是最近最少使用的,尾部是最近使用的,因此访问的条目被移动到尾部。在驱逐时,头部条目是受害者,它被取消链接并从表中删除。

    现在考虑到期。实践中发现的策略会根据最后一次读取(time-to-idle)或最后一次写入(time-to-live)重置超时。这听起来可能类似于上面描述的 LRU 算法,因为它基于相同的访问模式维护排序。唯一的区别是缓存确定需要驱逐的时间:大小与时间。因此,我们可以应用相同的算法,只是改变我们检测溢出的方式!

    这意味着您可以实现 LRU 算法并泛化评估谓词以允许在容量限制到时间限制之间切换。结果是时间和空间有效的过期缓存。

    【讨论】:

    • 嗨,本,感谢您抽出宝贵时间回答。我只对基于时间的过期感兴趣,除了超时之外没有任何丢失数据的风险。这基本上是一个带有超时的字典,但它是一个高度并发的字典。
    • @Teleo,我明白这一点。我的观点是,构建 LRU 缓存的算法可以很容易地改用基于时间的驱逐。这只是将评估标准从大小更改为时间限制的问题。如果可以实现并发 LRU,那么也可以实现并发过期缓存。并发 LRU 实际上相当简单但不明显,但如果您有兴趣,我可以提供这些细节和 Java 实现。
    • 我找到了你的ConcurrentLinkedHashMap 并喜欢阅读它。我明白您使用相同算法并进行一些调整的观点(例如避免维持最大重量)。尽管如此,您的代码在其核心中使用 Java 并发集合。至少,他们的 .Net 同行不适合这项工作。例如,删除一项 ConcurrentDictionary 会锁定其中一个锁条。 100,000 次删除将执行得非常糟糕,一次又一次地锁定相同的 Monitor 锁并花费大量时间。 (续...)
    • @Teleo,您可以通过在检索时评估条目的新鲜度并在其过期时假装缓存未命中来解决争用问题。可选地,这也可以使用清道夫线程。我在我的 ExpirableCache 教程(参见项目的 wiki)中做到了这一点,该教程是我在实现 LRU 特性之前编写的,因此它使用 O(lg n) 优先级队列。我在编写并发算法时一直采用的方法是解决锁争用问题,而不是尝试完全移除锁。当无锁算法过于复杂时,这往往更简单且更具可扩展性。
    • 我将链接到该项目,因为它非常有价值:code.google.com/p/concurrentlinkedhashmap
    猜你喜欢
    • 2017-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-03
    相关资源
    最近更新 更多