MemoryCache范围会话还是应用程序范围?

atc*_*way 45 asp.net caching memorycache

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

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

但是我注意到每个新的客户端呼叫(仍然在那个1小时的窗口内 - 事实上只是一分钟或者之后的两分钟)似乎第一次调用我的服务(即进行缓存)几乎和原来一样长在缓存数据之前调用.

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

Ram*_*nas 70

来自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并调查项目失效的原因是什么.

  • 非常彻底的答案,并感谢有关应用程序池超时的提醒.事件尽管没有考虑到每分钟的解释,但它总体上是有用的.我正在使用`MemoryCache.Default`和`cache.AddOrGetExisting`.在调试期间,逻辑运行完美.并且同一客户端的快速后续请求正如预期的那样从缓存中提取.这是调查我的问题的好信息. (4认同)
  • 我想给你 +1,但这会让你的等级达到 70,我觉得这是一种伤害。 (2认同)

atc*_*way 29

回顾这一年后,我发现了一些关于缓存"随机丢弃"的原始帖子的更多信息.在MSDN规定的配置缓存属性以下CacheMemoryLimitMegabytesPhysicalMemoryLimitPercentage:

默认值为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.
Run Code Online (Sandbox Code Playgroud)

具体的值并不一定与实现为什么经常使用缓存一样重要:存储我们不想一遍又一遍地获取的对象.如果这些对象存储在缓存中并且超出了基于这些内部计算的托管环境内存阈值,则可以自动从缓存中删除该项.这当然可以解释我的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>
Run Code Online (Sandbox Code Playgroud)