【问题标题】:Memorycache won't store my objectMemorycache 不会存储我的对象
【发布时间】:2015-01-29 15:45:03
【问题描述】:

所以我围绕 System.Runtime MemoryCache 编写了几个包装器方法,以便在我的 ASP.NET MVC 应用程序中为每个视图模型获取一个通用/用户绑定的缓存上下文。

在某些时候,我注意到我的委托只是每次都被调用,而不是无缘无故地检索我存储的对象。

奇怪的是,我的所有单元测试(使用简单的数据来检查它)都没有失败或显示出解释这一点的模式。

这是其中一种包装方法:

    public T GetCustom<T>(CacheItemPolicy cacheSettings, Func<T> createCallback, params object[] parameters)
    {
        if (parameters.Length == 0)
            throw new ArgumentException("GetCustom can't be called without any parameters.");

        lock (_threadLock)
        {
            var mergedToken = GetCacheSignature(parameters);
            var cache = GetMemoryCache();
            if (cache.Contains(mergedToken))
            {
                var cacheResult = cache.Get(mergedToken);
                if (cacheResult is T)
                    return (T)cacheResult;

                throw new ArgumentException(string.Format("A caching signature was passed, which duplicates another signature of different return type. ({0})", mergedToken));
            }

            var result = createCallback(); <!-- keeps landing here
            if (!EqualityComparer<T>.Default.Equals(result, default(T)))
            {
                cache.Add(mergedToken, result, cacheSettings);
            }

            return result;
        }
    }

我想知道这里是否有人知道导致对象在 MemoryCache 中存储无效的条件。

在此之前,我将只删除我的复杂类的属性,直到存储工作。

不过,体验会很有趣。

【问题讨论】:

  • @Andreas Experience - 我在构造函数中设置了一个固定的到期日期时间,所以我的所有单元测试都通过了,然后在生产中,在日期过去之后,我不再能够缓存任何东西。听起来很相似。检查缓存设置是否为每个缓存提供了合理的(和未来!)到期日期。Add() 调用
  • @AlexeiLevenkov ASP.NET MVC 5.2
  • @Kaido 有问题的方法确实将 DateTimeOffset.Now.AddMinutes(5) 作为绝对到期日期传递。所以不应该是这样。还是谢谢
  • @Andreas 该日期时间是否保存在一个保存超过 5 分钟的属性中?
  • @Kaido 每次通话都有可能是新的。在我的测试中,它工作得很好。一旦找不到相应的缓存元素,它就会执行委托并将该对象与传递的策略一起存储。问题是由于某种原因它不适用于我的复杂类型

标签: c# asp.net-mvc memorycache


【解决方案1】:

发生这种情况的常见原因有几个(假设逻辑正确,可以将对象实际添加到缓存/找到正确的缓存实例):

  • x86(32 位)进程需要处理“非常少”的内存量 - 在缓存(或缓存的特定实例)之外消耗过多内存相对容易,结果项目将立即从缓存。
  • ASP.Net 应用程序域由于各种原因而被回收也会清除缓存。

注意事项

  • 通常,您会将“每个用户缓存的信息”存储在会话状态中,以便对其进行适当管理,并且可以通过 SQL/其他进程外状态选项进行持久化。
  • 如果您需要支持更多的用户,依靠缓存每个用户的对象可能不会提高性能。您需要仔细衡量对预期负载水平的影响。

【讨论】:

  • 我已尝试附加一个已移除的委托以尽快检测这些驱逐。 (因为我在另一个问题中读过它)。你认为可能有内存缓存立即拒绝对象而不触发removed事件的情况吗?
  • @AndreasMüller 我不知道,但如果是这种情况也不会感到惊讶 - 太多人试图在过期时立即将对象重新插入缓存......如果你有兴趣试试查看代码 - referencesource.microsoft.com
  • 是的。我会看看那个。遗憾的是,从事情的外观来看,您可能指向了正确的方向。
  • 我的开发环境是在一个相当缺乏内存的虚拟机中。每当我运行我的测试用例时,内存就足够了。但是,当启动 Web 应用程序时,我的内存消耗大到足以触发立即驱逐的阈值。谢谢。
猜你喜欢
  • 1970-01-01
  • 2015-03-04
  • 2023-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-11
  • 1970-01-01
相关资源
最近更新 更多