【问题标题】:ASP.net CachingASP.net 缓存
【发布时间】:2011-03-14 14:02:01
【问题描述】:

我已经实现了 asp.net 缓存。但我得到了奇怪的结果

与大多数缓存不同,您试图避免对数据库的点击量。我试图避免用户对数据库的任何点击。这是第一个页面加载所需的时间。它基本上是一个包含大量图表和长时间运行查询的仪表板

我尝试了几种技术 1)缓存时间很长,有一个调度进程过期并获得新的缓存。 2) 并在 RemoveCallback 上

在第二个选项中,我让所有缓存都通过我创建的静态类。目的是在过期时刷新数据。这就是我所说的。

Cache.Insert(dbCacheString, dtNetwork, null, DateTime.Now.AddHours(2),
    System.Web.Caching.Cache.NoSlidingExpiration, CacheItemPriority.High, 
    new CacheItemRemovedCallback(CacheManager.CacheRemovedCallback));

    public static class CacheManager
    {
        private static Hashtable times = new Hashtable();
        private static bool isRefreshingCache = false;

        public static void CacheRemovedCallback(String key, object value,
            CacheItemRemovedReason removedReason)
        {
            RefreshCache(key);
        }

        public static void StartCache()
        {
            string lcUrl = "http://localhost/ratingspage/";
            // *** Establish the request 

            try
            {

                WebClient client = new WebClient();
                client.Credentials = new NetworkCredential("xxx", "xxx", 
                    "xxx");
                byte[] myDataBuffer = client.DownloadData(lcUrl);


            }
            catch (Exception ex)
            {
                ErrHandler.WriteError(ex.Message + "\n" + 
                    ex.StackTrace.ToString());
                LogUtil.LogDebugMessages(ex.Message + ":" + 
                    ex.StackTrace.ToString());
            }

        }

        public static void RefreshCache(string key)
        {
            string controlname = "";
            if ( key.ToLower().StartsWith("control:") )
            {
                string[] tmp = key.Split(':');
                if (tmp.Length > 1)
                    controlname = tmp[1];
                else
                    return;
            }
            else
                return;

            string lcUrl = "http://localhost/ratingspage/Admin/" + "
                "LoadControl.aspx?CachingSpider=true&Control=" + controlname;
            string lcHtml = isRefreshingCache.ToString();
            // *** Establish the request 

            if (!isRefreshingCache)
            {

                isRefreshingCache = true;
                lcHtml = isRefreshingCache.ToString();
                try
                {

                    WebClient client = new WebClient();
                    client.Credentials = new NetworkCredential("xxx", 
                        "xxx", "xxx");
                    byte[] myDataBuffer = client.DownloadData(lcUrl);
                    lcHtml = Encoding.ASCII.GetString(myDataBuffer);

                }
                catch (Exception ex)
                {
                    lcHtml = ex.Message;
                    isRefreshingCache = false;
                    ErrHandler.WriteError(ex.Message + "\n" + 
                        ex.StackTrace.ToString());
                    LogUtil.LogDebugMessages(ex.Message + ":" + 
                        ex.StackTrace.ToString());
                }
                isRefreshingCache = false;
            }



            MailMessage mail = new MailMessage(
                new MailAddress("jgiblin@univision.net"), 
                new MailAddress("jgiblin@univision.net"));
            mail.Subject = "Cache Expire: " + key;
            mail.Body = string.Format("The Key {0} has expired at {1}", 
                key, DateTime.Now.ToShortDateString() + " " +
                DateTime.Now.ToShortTimeString()) + "\nRefreshing Cache: " + 
                lcHtml;
            SmtpClient smtp = new SmtpClient("mercury.utg.uvn.net");
            mail.IsBodyHtml = false;
            try
            {

                smtp.Send(mail);

            }
            catch (Exception ex)
            {
                ErrHandler.WriteError(ex.Message + "\n" + 
                    ex.StackTrace.ToString());
                LogUtil.LogDebugMessages(ex.Message + ":" + 
                    ex.StackTrace.ToString());
            }

        }
    }

由于某种原因,当我转到该页面时。有时数据会被缓存,有时则不会。这里有什么问题吗

我尝试了应用程序结构,但由于服务器没有 iis 7,我无法使用它

【问题讨论】:

  • 您确定没有在两次访问之间重新启动 appdomain(即按 F5 进行调试会清除缓存)。
  • 只是一些建议,我认为您可以通过不将应用程序代码与缓存管理器交织在一起来改善这一点。 CacheManager 应该只在您使用的任何底层缓存系统(redis、其他)中获取/设置键/值。在您现有的业务逻辑中,例如获取用户,您检查缓存,如果它为空,您从数据库中检索,放入缓存然后返回项目。如果缓存确实包含用户,那么您只需从缓存中返回用户并跳过您的数据库查询。

标签: c# asp.net caching


【解决方案1】:

在我看来,您的 RefreshCache 调用中可能存在竞争条件。查看这个很好的答案以获取有关如何处理同步的建议:

C# version of java's synchronized keyword?

如果我是你,我会简化我的代码。你只需要:

  1. 应用启动时,加载缓存
  2. 当缓存过期时,重新加载它
  3. 如果用户尝试访问缓存对象但未命中,则将其线程休眠一秒钟并再次检查

【讨论】:

  • 我认为这不是同步问题。这些项目最初确实会被缓存,但问题是它不会在缓存中保留那么久。我将超时设置为 24 小时,但仍会在一小时后到期。我还尝试在 web.config 中使用
【解决方案2】:

您可以进入缓存的数据量可能是问题所在。

如果缓存已满,那么数据显然不会被缓存。

您可以使用process monitor 检查您的内存分配,查看“Cache Total Entries”。

【讨论】:

  • 我如何检查这个。我找不到任何东西
  • 看看这个 - msdn.microsoft.com/en-us/library/… 它应该有帮助
  • 谢谢。我想我知道为什么我会丢失缓存。我查看了事件查看器,发现我有一个 .net 4 Stack 溢出。我仍在努力解决这个问题。
  • 很高兴我能帮上忙,希望你继续解决它。如果我有帮助,您能否接受答案和/或投票。如果您接受答案,您下次更有可能从社区获得帮助。干杯。
猜你喜欢
  • 2010-09-05
  • 2011-09-09
  • 2010-11-10
  • 1970-01-01
  • 2012-06-05
  • 2016-04-23
  • 1970-01-01
  • 2014-10-26
相关资源
最近更新 更多