缓存机制

来源:互联网 发布:人工智能三大定律 编辑:程序博客网 时间:2024/06/05 11:51

一. 为什么要使用缓存

如果每次进入页面的时候都查询数据库生成页面内容的话,如果访问量非常大,则网站性能会非常差。而如果只有第一次访问的时候才查询数据库生成页面内容,以后都直接输出内容,则能提高系统性能。这样无论有多少人访问都只访问一次数据库,数据库压力不变。

二. 什么是缓存:

缓存(Cache)是一种用空间换取时间的技术,存在于计算机中很多地方,用来将一些慢速设备中的常用数据保存在快速设备中,取数据的时候直接从快速设备中取。比如CPU二级缓存、内存、windows文件读取缓存。缓存是改进网站性能的第一个手段,就像索引是改进数据库性能的第一个手段一样

 

三. 缓存存在的问题:

   缓存存在失效的问题:为了保证从缓存中读取数据和慢速数据(数据库)中数据一致,则需要在慢速数据(数据库)中对应的数据发生变化的时候,清除缓存中相应的数据(缓存依赖)。

四. 下面介绍asp.net中的三种形式的缓存:

  页面缓存(中庸)、数据源缓存(最不灵活的)、数据缓存(灵活)这三种主要类型。

 

1) 页面缓存:

简单的有关介绍:

给页面添加<%@ OutputCache Duration=15”  VaryByParam=none%>标签就可以启用页面缓存,这样整个页面的内容都会被缓存,页面中的ASP.Net代码、数据源在缓存期间都不会被运行,而是直接输出缓存的页面内容。 Duration表示缓存时间,以秒为单位,超过这个时间则缓存失效,再次生成以后会再缓存15秒,以此类推。在Page_Load处设置断点、修改数据库数据测试。这个缓存是在服务器缓存的,不是在客户端,因为用HttpWatch还是能看到向服务器提交的请求的,只不过服务器看到有缓存就没有再执行页面类。一般只有看帖、看新闻、看视频的页面才缓存,CUD的页面没必要缓存。

缓存是针对所有这个页面的访问者。这样1个访问者和1万个访问者、一次访问和100万次访问对数据库的压力是一样的。

下面开始介绍也页面缓存机制:

当浏览器第一次请求页面后,发送了请求报文,服务器端会分析请求的报文,然后判端服务器缓存中有没有该页面的数据的html代码,有发送304告诉浏览器,你那边(浏览器端)有该页面的缓存数据,发送Last-Modified时间。告诉浏览器从浏览器那边拿数据。没有就重新运行页面,创建页面类,读取数据库,返回数据,产生html代码放在服务器缓存区,并设置缓存事件时间为多少,并发送html代码给浏览器。当改浏览器再次发送同一个页面的请求时,会带着上次发来的Last-Modified

时间放在请求报文里,服务器接受到请求报文,分析,一看,这个时间还在设置的缓存时间之内,然后发送304给浏览器,还有Last-Modified时间,告诉浏览器,从自己的缓存区中拿数据html代码。此时,在服务器端没有创建页面类。减少了服务器端的负载。

 

但是问题来了:那么为什么在服务器端也设置服务器端缓存呢?

 

这是为了,其他用户的浏览器访问同一个页面时候,服务器要判断服务器端有没有该页面的缓存的html代码,如果有的话,那么就把这个缓存区的html代码发给这个用户的浏览器,

还有一个时间Last-Modified。此时浏览器会在下次再访问该网站页面的时候以If-Modified-Since值的方式提交的服务器。那么服务器就会向上面一样,返回状态码304给服务器。让浏览器从自己的换存中读取数据。他们之间的通信主要通过Last-Modified,

       If-Modified-Since进行判断缓存是否消失。

 

   但是问题又来了:

 

对于看新闻页面来讲,如果如上设置的话,则会缓存在第一个看到的新闻,因为?id=2?id=3只是页面的不同参数而已,为了能让不同的新闻各自缓存,因此可以设置VaryByParam=id”,表示对于相同页面的不同的id参数进行单独缓存。如果有多个确定缓存的参数,则将参数名用分号隔开即可,比如VaryByParam=id;number”。测试。缓存可能会有过期数据的问题,因此根据需求选用。

如果想让任何不同的查询字符串都创建不同的缓存,则设置VaryByParam="*",一般情况下设置“*”就足够。

所以设置VaryByParam=none“是不管你带上什么参数,在服务器端缓存的都是第一次访问的页面。 如果参上多个参数,就会根据你的参数来缓存不同的页面的数据的html代码。

 

2) 数据源缓存:

设定ObjectDataSourceCacheDuration(缓存时间:秒),EnableCaching=true。这样每隔CacheDuration指定的时间段才调用SelectMethod指定的方法来执行数据库查询,其他时候都是直接返回缓存的数据。取数据的过程缓存,在缓存期间,绑定控件向ObjectDataSource要数据, ObjectDataSource直接将缓存的数据返回给控件,不再去向TypeName指向的类要数据。

 

注意:

缓存固定的时间适用于首页、文章列表等访问频繁的页面,对于看贴页面则不适合,假设有100万个帖子,如果每个帖子都是固定缓存1小时的话,假设一小时之内有10万个帖子被看了,那么就要缓存十万个帖子,非常占用内存,因为百年一看坟帖偶然被访问一次也缓存一个小时,占用内存。这时候可以采用滑动窗口(sliding策略,比如帖子缓存10分钟,如果10分钟之内又访问了,则缓存的失效时间修改为从被访问这一刻起的10分钟之后,以此类推。这样经常访问的帖子就可以长期缓存,而不经常访问的帖子也不会因为偶然访问而长期占用缓存。设置方法,数据源:CacheExpirationPolicy="Sliding"。面试可聊。todo:貌似滑动有问题。不是问题,Sliding只是策略,服务器会参考。

 

3)缓存依赖:

 依赖于文件内容
CacheDependency cDep new CacheDependency(filePath);

依赖于数据库内容(轮询机制/通知机制)
一:轮询机制 fw主动到数据库检查数据是否改变
1.使用C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727中的aspnet_regsql.exe
注册:aspnet_regsql -S -E -ed -d 数据库名 -et -t 表名
删除:aspnet_regsql -S -E -d 数据库名 -dt -t 表名
取消数据库缓存依赖aspnet_regsql -S -E -dd 数据库名
数据库名 列出已注册表:aspnet_regsql -S -E -d 数据库名 -lt
2.配置web.config(见备注)
3.数据库依赖对象
SqlCacheDependency cDep 
   new SqlCacheDependency("GSSMS", "Students");

 

下面介绍两种依赖的详细:

1.依赖于文件System.Web.Caching.CacheDependency cDep new System.Web.Caching.CacheDependency(filePath);

Cache.Add("fmsg", msg, cDep, System.Web.Caching.Cache.NoAbsoluteExpiration, System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.Normal, RemovedCallback);

aspnet_regsql -S -E(集成登陆)/-U sa -P 123 -ed(启动/-dd关闭-d(数据库名GSSMS -et(指定缓存依赖的表名/-dt禁用表名-t(表名Aticle
2.依赖于数据库的web.config配置
<system.web>

<caching>

<sqlCacheDependency enabled="true">

<databases>

<add name="GSSMS" connectionStringName="conStr2" pollTime="15000"/>

</databases>

</sqlCacheDependency>

</caching>

 

4.自定义缓存:

定义缓存使用类Cache,使用时先判断有没有缓存数据

if (Cache["uList"!= null)

    {

     sbHtml Cache["uList"].ToString();

     Response.Write("缓存里有数");

     }

这个和Session保存,取出差不多。

 1.使用 绝对过期时间设置缓存

Cache.Insert("uList",sbHtml,null,DateTime.Now.AddSeconds(15),System.Web.Caching.Cache.NoSlidingExpiration);

2.使用相对过期时间 设置缓存

 Cache.Insert("uList", sbHtml, null,DateTime.MaxValue, new TimeSpan(0, 0, 15));

其中uList是要缓存的对象的数据。

3 0
原创粉丝点击