使用HttpRuntime.Cache发布问题

use*_*042 4 c# asp.net caching

我使用以下.net代码将对象添加到缓存中:

public static void Add<T>(string key, T dataToCache)
{
    try
    {
        ApplicationLog.Instance.WriteInfoFormat("Inserting item with key {0} into Cache...", key);

        HttpRuntime.Cache.Insert(
            key,
            dataToCache,
            null,
            DateTime.Now.AddDays(7),
            System.Web.Caching.Cache.NoSlidingExpiration);
    }

    catch (Exception ex)
    {
        ApplicationLog.Instance.WriteException(ex);             
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我从缓存中检索值的代码:

public static T Get<T>(string key) 
{   
    try
    {                
        if (Exists(key))
        {
            ApplicationLog.Instance.WriteInfoFormat("Retrieving item with key {0} from Cache...", key);

            return (T)HttpRuntime.Cache[key];
        }
        else
        {
            ApplicationLog.Instance.WriteInfoFormat("Item with key {0} does not exist in Cache.", key);
            return default(T); 
        }
    }
    catch(Exception ex)
    {
        ApplicationLog.Instance.WriteException(ex);
        return default(T); 
    }
}


public static bool Exists(string key)
{
    bool retVal = false;
    try
    {
        retVal= HttpRuntime.Cache[key] != null;
    }
    catch (Exception ex)
    {
        ApplicationLog.Instance.WriteException(ex);
    }
    return retVal; 
}
Run Code Online (Sandbox Code Playgroud)

但我发现每隔2分钟左右,缓存的对象值将被设置为null,从而再次从数据库中提取该值.

我在这里失踪了什么?

use*_*706 8

首先,您的访问权限不同步,因此这是一个很好的问题来源.从HttpRuntime Cache读取保证是线程安全的,因此您应该尝试读取您的项目作为每个缓存操作的第一步.

在检查是否Exists和实际检索项目之间可能发生很多事情(例如您的项目不再在那里).您应该获得正在寻找的项目的句柄,如果不是,那么通过从持久性数据存储中获取它来提供线程安全插入.

因此,您的Add逻辑将进入您的GetIF,数据不存在.提供单独的Add逻辑并没有什么根本性的错误,与阻止对特定数据的进一步请求相比,您应该多次测量数据库的成本.

T GetT(string key)
{
    T item = (cache.Get(key) as T);
    if (item == null)
    {
        lock (yourSyncRoot)
        {
            // double check it here
            item = (cache.Get(key) as T);
            if (item != null)
                return item;

            item = GetMyItemFromMyPersistentStore(key); // db?
            if (item == null)
                return null;

            string[] dependencyKeys = {your, dependency, keys};

            cache.Insert(key, item, new CacheDependency(null, dependencyKeys), 
                         absoluteExpiration, slidingExpiration, priority, null);
        }
    }
    return item;
}
Run Code Online (Sandbox Code Playgroud)

根据您的到期政策,您可以将数据存储在内存中,并提供快速和同步的访问权限,但正如我所说,测量它并根据您的需要进行调整.在更新项目并将其正确保存到持久存储之后的业务逻辑中,只需将其从缓存中删除,然后下一次调用Get将再次获取它.

  • @eych,"缓存访问是线程安全的"意味着对象上的单个操作以原子方式运行,并且在被多个线程命中时不会导致失败.但是,对象上的多个操作仍然需要通过锁同步,即使对于线程安全的集合也是如此.如果get没有找到对象,我们在这里有一个"Get"和一个"Insert".必须锁定该对,否则两个或多个不同的线程可以通过"获取",找不到对象,并创建并"插入"它.如果我们只想创建一个线程并插入对象,则必须锁定操作对.常见的模式. (5认同)

col*_*ium 6

当你说每两分钟插入的值被设置为null时,这是否意味着你感兴趣的项目或缓存中的每个项目?

我问这个是因为只要应用程序正在运行,缓存就会存在.如果重新启动应用程序,缓存就会消失.这可以解释如果每2分钟一切都消失的行为.在这种情况下,您手上会遇到不同的问题:为什么应用程序每2分钟重新启动一次.

如果它只是一些项目,那么它可能是一个内存问题.缓存会自行清理以响应内存不足.我相信有一种方法可以为插入的值设置优先级.但是当你内存不足时,这应该只是一个问题.

如果这仍然无法解决您的问题,有一种方法可以发现为什么要删除某个项目.这里解释一下.