C# 流行内容的asp.net缓存实现

C# 流行内容的asp.net缓存实现,c#,asp.net,caching,C#,Asp.net,Caching,在下面的代码中,我想实现这一点:每当用户要求特定的内容时,我首先检查是否已在当天从数据库中获得该内容。 如果是,我将返回缓存的内容。如果没有-我首先从数据库中重新检索内容,将其返回给用户,并将其缓存,以便从今天开始的下一个请求使用,依此类推。。 我想知道的是,这是否是一个很好的代码实践,可以在流行内容上节省(大量)DB时间。(我不太关心代码示例的外观,因为它只是为了这个问题而编的,不会像在我的应用程序中那样使用。) 代码示例: public class ContentCachingExample

在下面的代码中,我想实现这一点:每当用户要求特定的内容时,我首先检查是否已在当天从数据库中获得该内容。 如果是,我将返回缓存的内容。如果没有-我首先从数据库中重新检索内容,将其返回给用户,并将其缓存,以便从今天开始的下一个请求使用,依此类推。。 我想知道的是,这是否是一个很好的代码实践,可以在流行内容上节省(大量)DB时间。(我不太关心代码示例的外观,因为它只是为了这个问题而编的,不会像在我的应用程序中那样使用。)

代码示例:

public class ContentCachingExample
{
    private static DateTime _lastRequestTime;
    private static MyContent _cachedContent;

    private static MyContent GetContent()
    {
        // compare dates - content will be re-retrieved from DB once a day.
        if (DateTime.Now.Date> _lastRequestTime.Date) 
        {
            _lastRequestTime = DateTime.Now;
            _cachedContent = GetContentFromDb();
        }
        return _cachedContent;
    }

    private static MyContent GetContentFromDb()
    {
        // get content from DB
    }

    public class MyContent
    {
        public string Property1 { get; set; }
        public int Property2 { get; set; }
    }
 }

这就是所谓的过早优化。你试图解决一个你(大概)不知道存在的问题

这通常是有害的。例如,如果您现在的性能不好,可能是因为受内存限制:例如,在同一台计算机上运行SQL Server和IIS,这太多了。在这种情况下,缓存DB内容策略不会有帮助,它会使事情变得更糟

如果查询中的DB查询需要很长时间来检索(直接由您测量,并确认用户等待的时间太长:您必须真正执行这两个步骤),那么您可能会按照您的建议考虑。不过,您需要查看ASP.NET

缓存
对象,而不是自己重新创建它。一个快速的谷歌会打开这个页面,这可能是一个很好的起点


除非您有性能问题,否则现在不要尝试解决它。您可以在开发过程中牢记这一点—这就是为什么您应该在开发应用程序时将关注点、模块化、分层结构、服务体系结构等明确分离:您可以在以后轻松添加“缓存层”,如果需要的话

是的,DB缓存是最佳实践的一部分,可以获得非常大的性能提升。如果您过于依赖它,那么最终可能会导致非常令人沮丧的性能,比如说在IIS worker刚刚重新启动之后,与它运行一小时后相比

记住要考虑缓存过期,如果这个流行内容发生了变化怎么办?您需要多长时间才能看到新内容?缓存时间比24小时小得多,因此性能得到了很大提升。如果你有一秒钟的页面浏览时间,1分钟的缓存时间将为你节省59次数据库访问,这意味着如果页面被删除,你有(很小)存活的机会

如果您使用的是MS-SQL,则有多种方法可以确定行或表是否发生更改

如果您使用的是ASP.NET,您可能还想进行investergate,这允许您根据URL参数缓存来自页面或控件的结果。这允许您使用缓存节省web服务器CPU和DB负载

试用


你所做的是一种常见的模式

您应该考虑一些存在的库,特别是如果您需要对缓存机制进行微调时。

David提到了System.Web.Cache

还有


但是,如果您只需要代码的当前功能,那么您所拥有的就可以了。

OP的问题:“我想知道的是,这是否是一种在流行内容上节省(大量)DB时间的良好代码实践”?您提供的代码正是我所需要的,但是你没有提到这是否是一个好的做法。@Kieren Johnstone Yea打字比我读的快:),我更新了我的答案,加入了我的信念,即缓存是一个好的做法缓存经常使用的资源肯定不是过早优化-这是一个好的做法。它肯定是过早优化。以我的例子:如果DB查询在10毫秒内返回,并且机器以100%RAM使用率运行,该怎么办?根据定义,优化应用程序以将DB查询结果存储在内存中,并假设它是一个瓶颈,这还为时过早。为什么这不是优化,这是不成熟的?由于速度问题(如果有)的性质尚不清楚,因此根据未知问题进行优化为时过早。我一般不同意这一点-对于我的解决方案,我每天只需要执行一次db查询。然而,为每个用户再次运行查询意味着我将尽可能多地运行查询(如果网站成功,访问量可能会很大。)你问这是否是一个糟糕的编码实践。考虑缓存是一个好主意,在不知道情况的情况下更充分地应用它是一个非常糟糕的想法。@ KieReNe-我看到了,你也没有在代码中提供任何日志记录、跟踪、异常处理、线程处理等吗?出于同样的原因?没有有效的理由来使用你所发布的代码,ASP.NET
Cache
对象几乎同样简单、经过验证、可靠,而且性能也将大大提高。正如我指出的,实现这种缓存可能不会提高性能,反而会使事情变得更糟。这是早熟的优化,如果你真的关心你的应用程序性能足以考虑这一点,好好考虑一下。如果你正在使用.NET 4,你也应该探索本地系统。运行时。Caching@Kieren-性能更高??为什么呢你不知道它在内部是如何工作的-用批评来支持你的陈述,为什么上面的内容没有被执行。。。除非缓存的数据量与可用内存相比很大,否则这只是常识,我会对任何为我工作的web开发人员提出严重的问题,因为他们没有掌握这一原则。@BonyT-例如,上面的代码将数据保留在内存中,即使系统内存不足。它将坚持到时间的尽头。ASP.NET
Cache
在内部使用
WeakReferences
(哦,看,我知道它在内部是如何工作的),因此如果系统内存不足,就不会出现大问题。因此,ASP.NET
缓存
对象是一个远比滚动您自己的对象好得多的选择,如上所述。我会的
private MyContent GetContent(){
   MyContent content = Cache[GetContentCacheKey()];
   if(content == null) {
     content = GetContentFromDb();
     Cache.Add(GetContentCaceKey(), content, null, DateTime.Now.AddHours(1), 
          Cache.NoSlidingExpiration, CacheItemPriority.High, null);
   }
   return content;
}