【问题标题】:Application Cache and Slow Process应用缓存和慢进程
【发布时间】:2013-06-02 09:46:10
【问题描述】:

我想使用应用程序缓存在我的 ASP.net 3.5 网站上创建一个应用程序范围的提要。我用来填充缓存的数据获取速度很慢,可能长达 10 秒(来自远程服务器的数据馈送)。我的问题/困惑是,构建缓存管理的最佳方式是什么。

private const string CacheKey = "MyCachedString";
private static string lockString = "";

public string GetCachedString()
{
    string data = (string)Cache[CacheKey];
    string newData = "";

    if (data == null)
    {
        // A - Should this method call go here?
        newData = SlowResourceMethod();

        lock (lockString)
        {
            data = (string)Cache[CacheKey];

            if (data != null)
            {
               return data;
            }

            // B - Or here, within the lock?
            newData = SlowResourceMethod();
            Cache[CacheKey] = data = newData;
        }
    }

    return data;
}

实际的方法将由 HttpHandler (.ashx) 呈现。

如果我在“A”点收集数据,我会缩短锁定时间,但最终可能会多次调用外部资源(来自所有试图引用提要的网页)。如果我把它放在'B'点,锁定时间会很长,我认为这是一件坏事。

什么是最好的方法,或者我可以使用更好的模式吗?

任何建议将不胜感激。

【问题讨论】:

  • 出于好奇,您为什么不使用像 memcached 或类似的预构建缓存解决方案? (stackoverflow.com/questions/3667433/…)
  • 我根本没有遇到预建的缓存解决方案,但我会调查 - 谢谢。

标签: asp.net caching webforms


【解决方案1】:

我在代码上添加了 cmets。

private const string CacheKey = "MyCachedString";
private static readonly object syncLock = new object();

public string GetCachedString()
{
    string data = (string)Cache[CacheKey];
    string newData = "";

    // start to check if you have it on cache
    if (data == null)
    {
        // A - Should this method call go here?
        // absolut not here
        // newData = SlowResourceMethod();

        // we are now here and wait for someone else to make it or not
        lock (syncLock)
        {
            // now lets see if some one else make it...
            data = (string)Cache[CacheKey];

            // we have it, send it
            if (data != null)
            {
               return data;
            }

            // not have it, now is the time to look for it.
            // B - Or here, within the lock?
            newData = SlowResourceMethod();
            // set it on cache
            Cache[CacheKey] = data = newData;
        }
    }

    return data;
}

对我来说更好的是使用mutex 并且锁定取决于名称CacheKey 而不是锁定所有资源和非相关资源。使用互斥锁,一个基本的简单示例是:

private const string CacheKey = "MyCachedString";
public string GetCachedString()
{
    string data = (string)Cache[CacheKey];
    string newData = "";

    // start to check if you have it on cache
    if (data == null)
    {
        // lock it base on resource key 
        //  (note that not all chars are valid for name)
        var mut = new Mutex(true, CacheKey);

        try
        {   
            // Wait until it is safe to enter.
            // but also add 30 seconds max
            mut.WaitOne(30000);

            // now lets see if some one else make it...
            data = (string)Cache[CacheKey];

            // we have it, send it
            if (data != null)
            {
               return data;
            }

            // not have it, now is the time to look for it.
            // B - Or here, within the lock?
            newData = SlowResourceMethod();
            // set it on cache
            Cache[CacheKey] = data = newData;

        }
        finally
        {
            // Release the Mutex.
            mut.ReleaseMutex();
        }    
    }

    return data;
}

您也可以阅读
Image caching issue by using files in ASP.NET

【讨论】:

  • 谢谢阿里斯托斯。您的回答全面且易于理解 - 非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-19
  • 2013-10-31
  • 2013-12-02
相关资源
最近更新 更多