以前写程序从来都没用过缓存(水平太菜),好在以前做的网站访问量都非常的小,所以性能问题也不突出,但是如果做一个正规的项目,不论大小,缓存技术是必须要使用到的。今天学习了三种常用的缓存技术,下面先讲第一种,非常的简单,相信大家一定能看明白。
先说下为什么要用缓存,在正常情况下,当一个用户要访问www.abc.com/index.aspx这个页面时,他的IE会给我们的网站服务器端发出一个浏览请求,我们的服务器收到请求后就会执行index.aspx文件相关的代码,执行完成后生成一个HTML文件,然后发送给用户的IE,如果有1000个人访问这个页面的话,哪服务器就要把index.aspx的代码执行1000次再发送1000次,在使用页面缓存技术之后我们把index.aspx页面缓存起来,这样就有可能做到1000个人访问,服务器只执行200次代码,再发送1000次,与前面相比较服务器少执行800次代码,大家想想看这会对服务器的效率有多么大的提高啊!如何做到这一点呢?请看“页面缓存”
页面缓存(OutPut Caching)
页面缓存的使用方法非常的简单,只需要在aspx页的顶部加一句声明
<%@ OutputCache Duration="60" VaryByParam="none" %>
Duration="60" 的意思是指定缓存的时间为60秒,可根据情况自已设定
VaryByParam="none" 的意思是设定无参数缓存(有参数的缓存下面会讲到)
这两个参数是必须的,不能缺省。另外还有一个重要的参数
DiskCacheable="true|false" 意思是要不要把缓存放到硬盘上,如果设为false则缓存数据会放到内存中。
这里需要注意一下,如果页面数据很小的话可以把缓存数据放到内存中,如果数据较大最好放到硬盘上,否则会占用大量内存影响服务器运行,如果数据缓存到硬盘上的话,记得要把Duration=""的值设的大一些如Duration="3600",如果设的太小,服务器会过于频繁的在硬盘上写数据反而会降低性能,如果在内存中缓存数据Duration""则不要设的太长,当然具体时间长短要大家自己多尝试才知道。
以上就是一个最简单的页面缓存的实现方法,再来回过头讲一下原理,先看个例子:
新建一个cache1.aspx文件,在页面开始处加一句<%@ OutputCache Duration="60" VaryByParam="none" %>然后在代码里写一句Response.Write(DateTime.Now),运行后显示出了当前时间,好,我们开始刷新这个页面,你会发现页面显示的时间停住不变,始终是第一次运行时的时间,现在,我们等待1分钟后再刷新页面,这时页面显示的时间变成了当前时间,再反复刷新,显示的时间又不变了,为什么呢?当第一个用户请求浏览cache1.aspx页时,服务器会执行cache1.aspx的代码生成一个HTML发送给用户,同时把这个HTML缓存到内存中,当第二次,第三次……发送浏览请求时,服务器不再执行cache1.aspx里的代码而是直接把缓存中的HTML发给用户端,60秒内都是如此,60秒后缓存被消除,当下一个请求出现时服务器会再执行cache1.aspx的代码,并把生成的HTML缓存60秒……
这里我们要注意一个问题,如果你的部分数据要求能够实时显示的话,那就不能使用整页缓存了,就要使用部分缓存,如何部分缓存,最简单的办法就是自定义一个用户控件,在用户控件里开头加<%@ OutputCache Duration="60" VaryByParam="none" %>的声明,这样当你在某个页面里使用这个控件时,页面里的其他数据不会被缓存,只有这个控件的内容会被缓存,具体就说了,很简单,大家自己试一试吧!
注意:DiskCacheable="true|false"的设置在VS2005正式版里不再正式支持,所以在MSDN里找不到关于它的说明,我咨询了微软的讲师,说是把缓存放到硬盘上在实际使用中会出现一些问题.现在我们在VS2005正式版里依然可以使用这个设置,但是会不会产生实际效果我就不清楚了,大家有知道的就说一声吧!
数据缓存
现在接着学习一下如何使用数据缓存,在讲数据缓存之前还要先说一下如果在页面中使用参数缓存。前面讲过一个缓存设置VaryByParam="none"为无参数,我们也可以对VaryByParam进行设置,设置的参数与随 GET 方法属性发送的查询字符串值对应,或与使用 POST 方法发送的参数对应。将该属性设置为多个参数时,对于每个指定参数组合,输出缓存都包含一个不同版本的请求文档。可能的值包括 none、星号 (*) 以及任何有效的查询字符串或 POST 参数名称。简单点说,就是设置成我们在页面中使用的QueryString名称,看个例子:
<% @ OutputCache Duration = " 60 " VaryByParam = " CustomerID " %>
<! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
< html xmlns ="http://www.w3.org/1999/xhtml" >
< head runat ="server" >
< title > 无标题页 </ title >
</ head >
< body >
< form id ="form1" runat ="server" >
< div >
< asp:GridView ID ="GridView1" runat ="server" BackColor ="LightGoldenrodYellow"
BorderColor ="Tan" BorderWidth ="1px" CellPadding ="2" ForeColor ="Black" GridLines ="None" >
< FooterStyle BackColor ="Tan" />
< SelectedRowStyle BackColor ="DarkSlateBlue" ForeColor ="GhostWhite" />
< PagerStyle BackColor ="PaleGoldenrod" ForeColor ="DarkSlateBlue" HorizontalAlign ="Center" />
< HeaderStyle BackColor ="Tan" Font-Bold ="True" />
< AlternatingRowStyle BackColor ="PaleGoldenrod" />
</ asp:GridView >
< br />
< br />
< asp:HyperLink ID ="HyperLink1" runat ="server" NavigateUrl ="~/date.aspx?CustomerID=16" > 16 </ asp:HyperLink >
< asp:HyperLink ID ="HyperLink2" runat ="server" NavigateUrl ="~/date.aspx?CustomerID=19" > 19 </ asp:HyperLink >
</ div >
</ form >
</ body >
</ html >
{
string conn, comm, id;
if (Request.QueryString[ " CustomerID " ] == null )
{
id = " 16 " ;
}
else
{
id = Request.QueryString[ " CustomerID " ];
}
conn = " Server=WEB/SQLEXPRESS;Uid=moon;Pwd=1qaz2wsx;Database=store " ;
comm = " SELECT * FROM orders WHERE CustomerID = " + id;
SqlDataAdapter da = new SqlDataAdapter(comm, conn);
DataSet ds = new DataSet();
da.Fill(ds);
GridView1.DataSource = ds.Tables[ 0 ];
GridView1.DataBind();
Response.Write(DateTime.Now.ToString());
}
运行后分别点击16和19会根据这两个关键字SELECT出不同的数据,这时候根据我们传递的两个参数会分别建立两个缓存页,在每点击一个关键字后请记住显示的时间,再反复刷新看看时间有什么变化!好了接下来讲一下数据缓存。
数据缓存(Data Caching)
在System.Web.Caching空间里有一个类“Cache”我们可以通过这个类对数据进行缓存。
最简单的缓存方法:Cache["MyCacheString"] = "My CSDN BLOG!!!"; 通过赋值的形式建立一个缓存,再通过赋值的形式取出缓存:myLabel.Text = Cache["MyCacheString"].ToString();这种方法使用非常的简单可是功能上受到了一些限制,为了更完善的订制缓存,应该使用Cache.Insert()方法,下面举个例子:
页面里只需要放一下GridView就可以了
using System.Web.Caching;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class DataCache : System.Web.UI.Page
{
DataView dv; // 先声明一个数据视图用来存放数据库里的数据表
protected void Page_Load( object sender, EventArgs e)
{
dv = (DataView)Cache[ " ds " ]; // 从缓存中读取数据表
if (dv == null ) // 如果缓存是空的,就建立数据库连接,从数据库里读数据
{
string conn, comm;
conn = " Server=WEB/SQLEXPRESS;Uid=moon;Pwd=1qaz2wsx;Database=store " ;
comm = " SELECT * FROM orders " ;
SqlDataAdapter da = new SqlDataAdapter(comm, conn);
DataSet ds = new DataSet();
da.Fill(ds);
dv = ds.Tables[ 0 ].DefaultView;
// 下面这句是关键,具体参数后面介绍
Cache.Insert( " ds " , dv, null , System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes( 3 ));
Databind();
Label1.Text = DateTime.Now.ToString(); // 参考用的时间,可有可无
}
else
{
Databind();
Response.Write( " Is Cache Data!!! " ); // 此句可有可无
}
}
protected void Databind() // 自定义的数据绑定方法
{
GridView1.DataSource = dv;
GridView1.DataBind();
}
}
参数说明
Cache.Insert (String, Object, CacheDependency, DateTime, TimeSpan) 1是缓存的名称,2是缓存的数据对象,3是缓存键依赖项,通常为Null,4是过期时间,如果使用相对过期时间则设为NoAbsoluteExpiration,5是可调过期时间,如果参数4使用了固定过期时间,则此参数要设成NoSlidingExpiration。呵呵是不是看的有点晕啊,举两个具体例子说一下过期时间的问题
Cache.Insert("ds", dv, null,DateTime.Now.AddMinutes(5) , System.Web.Caching.Cache.NoSlidingExpiration);
在这个例子里当缓存建立后过5分钟就过期。
Cache.Insert("ds", dv, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(5));
这个例子里缓存建立后,过期时间为可调,比如1:20秒建立的缓存过期时间应该是6:20但如果在3:20有人访问了缓存,则过期时间将调整为8:20,以此类推……
我们在VS2005里建立一个测试看看使用缓存前和使用缓存后的性能变化吧!看到没有,没有缓存前用了0.43秒而使用缓存后只用了0.08秒性能相差5倍多啊!!!
//用于缓存的策略
using System.Web.Caching;
Cache.Insert("Data" , ds);
//绝对时间过期。DateTime.Now.AddSeconds(10)表示缓存在10秒后过期,TimeSpan.Zero表示不使用平滑过期策略。
Cache.Insert("Data", ds, null, DateTime.Now.AddSeconds(10 ), TimeSpan.Zero);
//变化时间过期(平滑过期)。DateTime.MaxValue 表示不使用绝对时间过期策略,TimeSpan.Fromseconds(10)表示缓存连续10秒没有访问就过期。
Cache.Insert("Data", ds, null, DateTime.MaxValue, TimeSpan.FromSeconds(10));
{
Response.Write("缓存无效" );
}
else
{
DataSet ds = Cache["Data"] as DataSet;
}
Cache.Remove("Data" );
//移除所有缓存
IDictionaryEnumerator CacheEnum = HttpRuntime.Cache.GetEnumerator();
while (CacheEnum.MoveNext())
{
Cache.Remove(CacheEnum.Key.Tostring());
}