51

MemoryCache在 ASP.NET 中使用,它运行良好。我有一个缓存了一个小时的对象,以防止从存储库中提取新的数据。

我可以看到缓存在调试中工作,而且一旦部署到服务器,在第一次调用并且对象被缓存之后,后续调用大约是 1/5 的时间。

但是,我注意到每个新的客户端调用(仍在 1 小时窗口内 - 实际上只是一分钟或 2 分钟后)似乎对我的服务(正在进行缓存)的第一次调用几乎与原始调用一样长在缓存数据之前调用。

这让我开始怀疑 - 是特定于会话的,并且每个进行调用的新客户端都在存储它自己的缓存,或者即使我知道数据已被缓存之后MemoryCache,是否还有其他原因导致第一次调用需要这么长时间?

4

2 回答 2

83

来自MSDN

Cache 和 MemoryCache 类之间的主要区别在于 MemoryCache 类已被更改,以使其可供非 ASP.NET 应用程序的 .NET Framework 应用程序使用。例如,MemoryCache 类不依赖于 System.Web 程序集。另一个区别是您可以创建 MemoryCache 类的多个实例,以便在同一个应用程序和同一个 AppDomain 实例中使用。

阅读并在反射代码中进行一些调查很明显这MemoryCache只是一个简单的类。您可以使用MemoryCache.Default属性来(重新)使用相同的实例,也可以根据需要构建尽可能多的实例(尽管建议尽可能少)。

所以基本上答案就在你的代码中。
如果您使用MemoryCache.Default,那么只要您的应用程序池存在,您的缓存就会存在。(提醒您,默认应用程序池空闲超时为 20 分钟,不到 1 小时。)

如果您使用创建它,new MemoryCache(string, NameValueCollection)则上述注意事项适用,加上您在其中创建实例的上下文,也就是说,如果您在控制器中创建实例(我希望不是这种情况),那么您的缓存适用于一个请求

很遗憾我找不到任何参考资料,但是……MemoryCache不保证根据您指定的缓存策略保存数据。特别是如果您正在运行您的应用程序的机器在内存上受到压力,您的缓存可能会被丢弃。

如果您仍然无法弄清楚早期缓存项失效的原因是什么,您可以利用RemoveCallback并调查项失效的原因是什么。

于 2013-05-22T10:29:52.677 回答
35

一年后回顾这篇文章,我在我的原始帖子中发现了更多关于缓存随机“丢弃”的信息。MSDN 对可配置缓存属性CacheMemoryLimitMegabytes和以下内容进行了说明PhysicalMemoryLimitPercentage

默认值为 0,这意味着默认使用 MemoryCache 类的自动大小启发式。

做一些反编译和调查,在类深处有预先确定CacheMemoryMonitor.cs的场景来定义内存阈值。以下是该类中对该AutoPrivateBytesLimit属性的注释的示例:

// Auto-generate the private bytes limit:
// - On 64bit, the auto value is MIN(60% physical_ram, 1 TB)
// - On x86, for 2GB, the auto value is MIN(60% physical_ram, 800 MB)
// - On x86, for 3GB, the auto value is MIN(60% physical_ram, 1800 MB)
//
// - If it's not a hosted environment (e.g. console app), the 60% in the above
//   formulas will become 100% because in un-hosted environment we don't launch
//   other processes such as compiler, etc.

不一定要了解为什么经常使用缓存:存储我们不想一遍又一遍地获取的大对象,具体值并不一定很重要。如果这些对象存储在缓存中,并且超出了基于这些内部计算的托管环境内存阈值,您可能会自动从缓存中删除该项目。这当然可以解释我的 OP,因为我在托管服务器上的内存中存储了一个非常大的集合,其中可能有 2GB 的内存在 IIS 中运行多个应用程序。

设置这些值有一个明确的覆盖。您可以通过配置(或在设置MemoryCache实例时)设置CacheMemoryLimitMegabytesPhysicalMemoryLimitPercentage值。这是来自以下MSDN链接的修改示例,我将其设置physicalMemoryPercentage为 95 (%):

<configuration>
  <system.runtime.caching>
    <memoryCache>
      <namedCaches>
          <add name="default" 
               physicalMemoryLimitPercentage="95" />
      </namedCaches>
    </memoryCache>
  </system.runtime.caching>
</configuration>
于 2014-09-25T15:03:12.570 回答