ASP.NET 中的缓存





5.00/5 (3投票s)
缓存作者:Prakash Singh Mehra简介:这是一种将常用数据存储到服务器内存中的方法,可以非常快速地检索到。
缓存
作者:Prakash Singh Mehra
简介:这是一种将经常使用的数据存储到服务器内存中,以便能够非常快速地检索的方法。因此,它提供了可伸缩性和性能。例如,如果用户需要频繁地从数据库中获取相同的数据,那么结果数据可以存储在服务器内存中,并在以后以更少的时间(更好的性能)检索。同时,应用程序可以处理相同时间内的更多页面请求(可伸缩性)。
缺点:假设服务器内存已满,则剩余数据将存储在磁盘上,这会降低整个系统的性能。这就是为什么自限制缓存技术是最好的;一旦服务器内存已满,数据就会被选择性地从服务器内存中移除,以确保应用程序性能不会下降。
缓存类型:基本上,缓存有两种类型
- 输出缓存-渲染的 HTML 页面在发送到客户端之前存储在缓存中。现在,如果其他客户端请求相同的页面,则已渲染的 HTML 页面将从服务器内存中检索并发送到客户端,从而节省了渲染和处理整个页面所需的时间。
- 数据缓存-耗时且经常请求的重要信息片段存储在缓存中。例如,从数据库检索的数据集。它与应用程序状态非常相似,但对服务器更友好,因为一旦缓存已满,数据就会被移除。
上面两种类型还构建了另外两种模型:
- 片段缓存-不缓存整个页面,而是缓存渲染的 HTML 页面的某个部分。例如:页面中使用的用户控件被缓存,因此每次渲染页面时都不需要加载它。
- 数据源缓存-这是内置在数据源控件(例如 XmlDataSource、SqlDataSource 等)中的缓存。它与数据缓存非常相似,但在这里缓存不是显式处理的,而是由数据源控件根据数据控件上进行的设置进行管理。
输出缓存:渲染的 HTML 页面在发送到客户端之前存储在缓存中。现在,如果其他客户端请求相同的页面,则已渲染的 HTML 页面将从服务器内存中检索并发送到客户端。这节省了渲染和处理整个页面所需的时间。因此,节省了创建控件、再次启动/运行页面周期以及执行代码所需的时间。
声明:要使用输出缓存,请在页面中声明以下行
<@ OutputCache Duration="20" VaryByParam="None">这意味着该页面将缓存 20 秒。如果任何客户端在此时间内请求同一页面,则会发送渲染后的页面。20 秒后,已渲染页面的更新/最新版本将替换早期版本。
注意:应用程序重新编译时,页面会自动移除。
输出缓存和查询字符串:输出缓存还支持查询字符串值来缓存特定页面。基于查询字符串参数值,不同的页面会被缓存。例如,在下面的声明中
<@ OutputCache Duration="20" VaryByParam="ProductID">
基于不同的 ProductId 值缓存页面的不同版本。稍后,当使用特定查询字符串值(ProductId 值)请求页面时,将检索匹配的页面。
也可以指定多个查询字符串参数。在这些情况下,两个参数的组合值将作为页面缓存的键。还有一个特殊情况,即参数为“*”。在这种情况下,页面将为查询字符串参数的所有单独组合进行缓存。
<@ OutputCache Duration="20" VaryByParam="*">
自定义缓存控件:它为用户提供了根据自己构建的自定义字符串缓存页面的灵活性。让我们看下面的例子
<@ OutputCache Duration="20" VaryByParam="None" VaryByCustom="Browser">
用户定义了一个自定义字符串,将用于生成自定义缓存字符串。在这种情况下,用户希望根据浏览器版本缓存页面。这需要在 global.asax 页面下实现以下方法(或应具有以下结构)
Public override function GetVaryByCustomString(byval context as HttpContext, byval arg as string) as string // Check for the requested type of caching. If (arg == "browser") then // Determine the current browser. dim browserName as string = _ Context.Request.Browser.Browser + Context.Request.Browser.MajorVersion.ToString() // Indicate that this string should be used to vary caching. return browserName Else if (arg=="SomeCustomString") then //Define the custom cache value for the custom string .................................................... Else MyBase.GetVaryByCustomString(context, arg) End If End Function
使用 HttpCachePolicy 类进行缓存:它包含以编程方式执行缓存的方法。Response.Cache 属性提供
HttpCachePolicy
类的实例。让我们看下面的例子Public sub CacheCurrentPage() // Cache this page on the server. Response.Cache.SetCacheability(HttpCacheability.Public) // Use the cached copy of this page for the next 60 seconds. Response.Cache.SetExpires(DateTime.Now.AddSeconds(60)) // Ensures that the browser can't invalidate the page on click of Refresh button Response.Cache.SetValidUntilExpires(true) End Sub
但是,通过代码嵌入缓存很麻烦。
片段缓存:有时需要缓存页面的某个部分。在这种情况下,该部分将被包装到用户控件中。然后将 OutputCache 指令包含在用户控件文件中。这样,只有用户控件部分将被缓存。
缓存配置文件:ASP.NET 2.0 引入了一个新选项,如果您需要将相同的缓存设置应用于一组页面,则该选项非常适合。此功能称为缓存配置文件,它允许您在 web.config 文件中定义缓存设置。使用 `
<configuration> <system.web> <caching> <outputCacheSettings> <outputCacheProfiles> <add name="ProductItemCacheProfile" duration="60" /> </outputCacheProfiles> </outputCacheSettings> </caching> ... </system.web> </configuration>
现在,您可以通过 CacheProfile 属性在页面中使用此配置文件
<%@ OutputCache CacheProfile="ProductItemCacheProfile" VaryByParam="None" %>
缓存配置:您还可以通过 web.config 文件配置 ASP.NET 缓存行为的各种详细信息。要配置这些设置,您可以使用上面描述的 `
<configuration> <system.web> <caching> <cache disableMemoryCollection="true|false" disableExpiration="true|false" percentagePhysicalMemoryUsedLimit="number" privateBytesLimit="number" privateBytesPollTime="HH:MM:SS"/> ... </caching> </system.web> ... </configuration>
- DisableMemoryCollection:阻止 ASP.NET 在内存不足时收集项
-
DisableExpiration:移除过期项。
-
PercentagePhysicalMemoryUsedLimit:设置 ASP.NET 将用于缓存的虚拟内存的最大百分比。
- PrivateBytesLimit:确定特定应用程序可以为其缓存使用的最大字节数,然后 ASP.NET 开始积极清理(从缓存中移除旧数据)。
- PrivateBytesPollTime:ASP.NET 检查使用的私有字节的频率。默认值为 1 秒。
数据缓存:数据缓存的基本原理是,您将创建成本高昂的项添加到特殊的内置集合对象(称为 Cache)中。此对象的工作方式与 Application 对象非常相似。但是,存在一些关键区别
- Cache 对象是线程安全的:这意味着您无需在添加或移除项之前显式锁定或解锁 Cache 集合。但是,Cache 集合中的对象本身仍然需要是线程安全的。
- 缓存中的项会自动移除:如果项过期,如果其依赖的某个对象或文件发生更改,或者服务器内存不足,ASP.NET 会移除该项。这意味着您可以随意使用缓存,而无需担心浪费宝贵的服务器内存。
- 缓存中的项支持依赖关系:您可以将缓存对象链接到文件、数据库表或其他类型的资源。如果此资源发生更改,您的缓存对象将被自动视为无效并释放。
但是,与应用程序状态一样,缓存的对象存储在进程中,这意味着如果应用程序域重新启动,它将不会持久化,并且无法在 Web 场中的计算机之间共享。
向缓存添加项:与 Application 和 Session 集合一样,您可以通过为新键名赋值来将项添加到 Cache 集合
Cache("Key") = “Value”
但更好的方法是使用 Insert() 方法。它有四个版本
-
- Cache.Insert(key, value):在指定键名下将项插入缓存,使用默认优先级和过期时间。
- Cache.Insert(key, value, dependencies):还包含一个包含 CacheDependency 对象的最后一个参数,该对象链接到其他文件或缓存项,并允许在这些项发生更改时使缓存项失效。
- Cache.Insert(key, value, dependencies, absoluteExpiration, slidingExpiration):还指示滑动或绝对过期策略(本节稍后定义)
- Cache.Insert(key, value, dependencies, absoluteExpiration, slidingExpiration, onRemoveCallback):此外,您可以提交一个指向您希望在项移除时调用的方法的委托。
滑动过期和绝对过期:两者不能同时使用。如果使用绝对过期,请将 slidingExpiration 参数设置为 TimeSpan.Zero。要设置滑动过期策略,请将 absoluteExpiration 参数设置为 DateTime.Max。
通过滑动过期,ASP.NET 会等待一段设定的不活动时间来处理被忽略的缓存项。以下是一个存储具有 10 分钟滑动过期策略且无依赖项的项的示例。因此,只有在 10 分钟内未使用的 çarpanatible 数据才会被删除。
Cache.Insert("MyItem", obj, null, DateTime.MaxValue, TimeSpan.FromMinutes(10))
通过绝对过期,我们设置了缓存项将被移除的特定日期和时间。以下是一个存储项正好 60 分钟的示例
Cache.Insert("MyItem", obj, null, DateTime.Now.AddMinutes(60), TimeSpan.Zero)
缓存依赖:基本上,缓存依赖分为两类
1. 文件和缓存项依赖:缓存项可以依赖于特定文件。当此文件被修改时,缓存将被失效。
// Create a dependency for the ProductList.xml file. CacheDependency prodDependency = new CacheDependency(Server.MapPath("ProductList.xml")); // Add a cache item that will be dependent on this file. Cache.Insert("ProductInfo", prodInfo, prodDependency);
缓存还可以依赖于其他缓存项。创建缓存键数组,并将该数组设置为其他缓存的依赖项。
Cache["Key1"] = "Cache Item 1"; // Make Cache["Key2"] dependent on Cache["Key1"]. string[] dependencyKey = new string[1]; dependencyKey[0] = "Key1"; CacheDependency dependency = new CacheDependency(null, dependencyKey); Cache.Insert("Key2", "Cache Item 2", dependency);此外,缓存项可以依赖于多个缓存依赖项。这称为聚合缓存依赖项。
CacheDependency dep1 = new CacheDependency(Server.MapPath("ProductList1.xml")); CacheDependency dep2 = new CacheDependency(Server.MapPath("ProductList2.xml")); // Create the aggregate. CacheDependency[] dependencies = new CacheDependency[]{dep1, dep2} AggregateCacheDependency aggregateDep = new AggregateCacheDependency(); aggregateDep.Add(dependencies); // Add the dependent cache item. Cache.Insert("ProductInfo", prodInfo, aggregateDep);
2. 数据库查询依赖:缓存项也可以依赖于 SQL 查询。在 SQL Server 2000 及更早版本中,这是一项繁琐的任务,但在 SQL Server 2005 中已简化。它需要遵循以下几个步骤,如下所述
1. 启用缓存通知-确保您的数据库已设置 ENABLE_BROKER 标志。假设我们使用 Northwind 数据库
Use Northwind ALTER DATABASE Northwind SET ENABLE_BROKER
2. 创建缓存依赖-根据下面的代码行。
string query ="SELECT EmployeeID, FirstName, LastName, City FROM dbo.Employees"; SqlCommand cmd = new SqlCommand(query, strConnectionString); SqlDataAdapter adapter = new SqlDataAdapter(cmd); // Fill the DataSet. DataSet ds = new DataSet(); adapter.Fill(ds, "Employees"); // Create the dependency. SqlCacheDependency empDependency = new SqlCacheDependency(cmd); // Add a cache item that will be invalidated if one of its records changesor a new record is added.Cache.Insert("Employees", ds, empDependency);
3. 调用静态 SqlDependency.Start() 以初始化 Web 服务器上的侦听服务。这只需要为每个数据库连接调用一次。一个调用它的地方是 global.asax 文件的 Application_Start() 方法。
4. 最后,调用
SqlDependency.Stop()
以分离侦听器。通常,这会在 Application_End() 方法下调用。
检索/删除缓存集合:没有清除整个数据缓存的方法,但您可以使用 DictionaryEntry 类枚举集合。这使您有机会检索每个项的键,并允许您使用类似这样的代码来清空集合
foreach item as DictionaryEntry in Cache Cache.Remove(item.Key.ToString()) next
或者
foreach item as DictionaryEntry in Cache itemList += item.Key.ToString() Next
特别提示:当您从缓存中检索项时,您必须始终检查 null 引用。这是因为 ASP.NET 可以随时删除您的缓存项。
缓存优先级:您还可以在将项添加到缓存时设置优先级。优先级仅在 ASP.NET 需要执行缓存清理时才有效,缓存清理是在内存不足时提前移除缓存项的过程。数据按以下顺序删除
低、低于正常、正常、高于正常、高
低项最有可能被删除。还有一个优先级,“不可移除”;这些项通常不会被删除。