内存缓存还是并发字典?

Posted

技术标签:

【中文标题】内存缓存还是并发字典?【英文标题】:Memory Cache or Concurrent Dictionary? 【发布时间】:2012-09-17 17:39:14 【问题描述】:

我希望在 WCF 服务的请求级别实现缓存。对该服务的每个请求都会执行大量的数据库调用。考虑多个数据收集器。我们需要允许一个数据收集器访问前一个数据收集器已经检索到的信息。

我希望通过为每个请求创建一个特定实例来为此使用新的 .Net 4.0 内存缓存。

这是个好主意吗?还是我应该简单地使用 Dictionary 对象?

顺便说一句:数据收集将是并行的,因此锁定会更加复杂,但我也可以使用并发收集。

【问题讨论】:

更新 - 我决定使用 Concurrent 集合,因为它比系统级内存缓存更能满足我的需求。 据我了解 MemoryCache 类,它是一个进程级缓存.. 甚至AppDomain级别的,没测试过。 【参考方案1】:

如果您不需要某种过期逻辑,我建议您使用并发集合。您可以轻松实现 single entry caching mechanism 组合 ConcurrentDictionaryLazy 类。这是 another 链接关于 Lazy 和 ConcurrentDictionary 组合。

如果您需要让您的项目过期,那么您最好使用内置的 MemoryCache 并实现double-checked locking pattern 以保证缓存项目的单次检索。可以在 Locking pattern for proper use of .NET MemoryCache 中找到双重检查锁定的现成实现。

【讨论】:

好的 - 我的想法是一样的,但我还是不明白“为什么?”其中。 MemoryCache 为我提供了一些特定于缓存的函数,例如 AddOrGet。当我转向并发集合时,我会失去它。过期功能是在并发收集还是 MemoryCache 之间进行选择的唯一原因吗? @zync 将 ConcurrentDictionary 与 Lazy 结合使用的想法是确保您在每个应用程序域中检索一次缓存项,并且永远不会更改它们。如果不是这种情况,MemoryCache 会更好。但是,如果您需要单条目检索逻辑,则使用 ConcurrentDictionary 更合适,因为 MemoryCache.AddOrGetExisting 方法需要一个值,并且您在检索该值时仍然必须实现锁定。但是使用 ConcurrentDictionary.GetOrAdd(TKey key, Func valueFactory) 与 Lazy 结合,您可以将所有锁定内容留给框架库。 顺便说一下,如果你的缓存项在你的服务启动之前就已经定义好了(即你没有动态缓存)并且你可以容忍一次加载缓存中的所有数据,你可以使用你的静态构造函数服务类来加载这些缓存项。这更好,因为静态构造函数保证在每个应用程序域中执行一次,并且在执行该类型的任何实例构造函数之前执行。很简单。 @YiğitYener 当然,除非您只有通过async API 才能获得数据(尽管您可以拥有ConcurrentDictionary<TKey,Task<TValue>> 甚至ConcurrentDictionary<TKey,Lazy<Task<TValue>>>)。

以上是关于内存缓存还是并发字典?的主要内容,如果未能解决你的问题,请参考以下文章

并发编程之内存模型

线程并发笔记

高并发之缓存

Tomcat从内存并发缓存方面优化方法

高并发内存池整体架构

高并发内存池整体架构