• 025-缓存Cache


    如果每次进入页面的时候都查询数据库生成页面内容的话,如果访问量非常大,则网站性能会非常差。而如果只有第一次访问的时候才查询数据库生成页面内容,以后都直接输出内容,则能提高系统性能。这样无论有多少人访问都只访问一次数据库,数据库压力不变。
    缓存(Cache)是一种用空间换取时间的技术,存在于计算机中很多地方,用来将一些慢速设备中的常用数据保存在快速设备中,取数据的时候直接从快速设备中取。比如CPU二级缓存、内存、windows文件读取缓存。
    缓存存在失效的问题:为了保证从缓存中读取数据和慢速数据(数据库)中数据一致,则需要在慢速数据(数据库)中对应的数据发生变化的时候,清除缓存中相应的数据。
    缓存是改进网站性能的第一个手段,就像索引是改进数据库性能的第一个手段一样。ASP.net缓存主要分为:页面缓存(中庸)、数据源缓存(最不灵活的)、数据缓存(灵活)这三种主要类型。

    1.缓存可以提高数据访问性能,原因是缓存的数据都在内存中。避免了磁盘I/O操作,或者数据库的网络连接等。
    2.缓存的数据,必须有一定的过期策略,否则实际的数据发生改变后,对应的缓存还是旧数据,就造成了数据不一致的问题。
    3.什么情况下才用缓存?
    1>访问的数据不会发生改变,或者是很少发生变化。
    2>数据频繁被访问。

    直接使用Cache

    1>直接使用Cache["content"],缓存与Session不同,所有用户都可以共享。永不过期,由服务器自己维护,当内存不够时,会将老的缓存释放掉。
    2>设置绝对过期日期。Cache.Insert("nowTime", DateTime.Now, null, DateTime.Now.AddSeconds(7), TimeSpan.Zero);
    3>设置滑动过期日期: Cache.Insert("nowTime", DateTime.Now, null, DateTime.MaxValue, TimeSpan.FromSeconds(5));

    if (Cache["nowTime"] == null)
    {
    Cache.Insert("nowTime", DateTime.Now, null, DateTime.MaxValue, TimeSpan.FromSeconds(5));
    }
    else
    {
    Response.Write("缓存中的时间:" + Cache["nowTime"]);
    }
    ----------------------------------------------------------

    if (Cache["time"] == null)
    {
    Cache["time"] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
    }
    Response.Write(Cache["time"]);
    ----------------------------------------------------------
    if (Cache["time"] == null)
    {
    Cache.Insert("time", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), null, DateTime.Now.AddSeconds(10), TimeSpan.Zero);
    }
    Response.Write(Cache["time"]);
    ----------------------------------------------------------
    if (Cache["time"] == null)
    {
    Cache.Insert("time", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), null, DateTime.MaxValue, TimeSpan.FromSeconds(5));
    }
    Response.Write(Cache["time"]);
    ----------------------------------------------------------

    页面缓存

    给页面添加<%@ OutputCache Duration=“15” VaryByParam=“none”%>标签就可以启用页面缓存,这样整个页面的内容都会被缓存,页面中的ASP.Net代码、数据源在缓存期间都不会被运行,而是直接输出缓存的页面内容。 Duration表示缓存时间,以秒为单位,超过这个时间则缓存失效,再次生成以后会再缓存15秒,以此类推。在Page_Load处设置断点、修改数据库数据测试。这个缓存是在服务器缓存的,不是在客户端,因为用HttpWatch还是能看到向服务器提交的请求的,只不过服务器看到有缓存就没有再执行页面类。一般只有看帖、看新闻、看视频的页面才缓存,CUD的页面没必要缓存。
    缓存是针对所有这个页面的访问者。这样1个访问者和1万个访问者、一次访问和100万次访问对数据库的压力是一样的。
    对于看新闻页面来讲,如果如上设置的话,则会缓存在第一个看到的新闻,因为?id=2、?id=3只是页面的不同参数而已,为了能让不同的新闻各自缓存,因此可以设置VaryByParam=“id”,表示对于相同页面的不同的id参数进行单独缓存。如果有多个确定缓存的参数,则将参数名用分号隔开即可,比如VaryByParam=“id;number”。测试。缓存可能会有过期数据的问题,因此根据需求选用。
    如果想让任何不同的查询字符串都创建不同的缓存,则设置VaryByParam="*",一般情况下设置“*”就足够。
    在WebUserControl中也可以像页面缓存一样设置控件的缓存。

    id;name 组合缓存条件:只有两个参数的值组成的字符不一样的时候,才产生缓存
    VaryByParam:分号分隔的字符串列表,用于使输出缓存发生变化。默认情况下,这些字符串对应于使用 GET 方法属性发送的查询字符串值,或者使用 POST 方法发送的参数。 将该属性设置为多个参数时,对于每个指定参数组合,输出缓存都包含一个不同版本的请求文档。可能的值包括 none、星号 ( *) 以及任何有效的查询字符串或 POST 参数名称。

    <%@ OutputCache Duration="10" VaryByParam="*" %>
    Duration="10",表示缓存时间10秒,10秒后过期(绝对过期)。
    VaryByParam="*" ,表示按每次请求的参数不同,为每个不同的请求进行缓存。VaryByParam="none" 表示为所有的请求(无论参数是否一致)都只建立一个缓存。
    VaryByParam="id"
    VaryByParam="id;name"

    数据源缓存

    演示手动绑定数据的时候通过Cache[]把List缓存,设置缓存时间。
    设定ObjectDataSource的CacheDuration(缓存时间:秒),EnableCaching=true。设置CacheExpirationPolicy=Absolute,该属性(过期策略)。这样每隔CacheDuration指定的时间段才调用SelectMethod指定的方法来执行数据库查询,其他时候都是直接返回缓存的数据。取数据的过程缓存,在缓存期间,绑定控件向ObjectDataSource要数据, ObjectDataSource直接将缓存的数据返回给控件,不再去向TypeName指向的类要数据。

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

    if (Cache["PersonList"] == null)
    {
    NewPersonBll bll = new NewPersonBll();
    IEnumerable<NewPerson> list = bll.GetAll();
    Cache["PersonList"] = list;
    }

    this.Repeater1.DataSource = Cache["PersonList"];
    this.Repeater1.DataBind();

    <asp:Repeater ID="Repeater1" runat="server" DataSourceID="ObjectDataSource1">
    <HeaderTemplate>
    <ul>
    </HeaderTemplate>
    <ItemTemplate>
    <li>
    <%#Eval("UName")%></li>
    </ItemTemplate>
    <FooterTemplate>
    </ul>
    </FooterTemplate>
    </asp:Repeater>
    <asp:ObjectDataSource ID="ObjectDataSource1" CacheDuration="10" EnableCaching="true" CacheExpirationPolicy="Sliding" runat="server" SelectMethod="GetAll"
    TypeName="Aspx.CRUD.BLL.NewPersonBll">
    </asp:ObjectDataSource>

    配置IIS输出缓存

    选择IIS→网站→输出缓存→添加

    内核缓存和IIS 7输出缓存
    当使用服务器上的输出缓存时,也可以使用内核缓存和IIS 7输出缓存。IIS 7首先引入输出缓存,但IIS6也已经支持内核缓存。从这些缓存中响应请求要比从ASP.NET输出缓存中快,因为它们是集成在IIS中的。下面是工作原理。

    当一个新的请求到达web服务器时,最先由内核驱动http.sys处理。这个驱动首先尝试从内核缓存中响应请求。如果不能,它会将请求发送到IIS的一个监听线程端口。这个IIS线程试图从IIS 7的输出缓存中响应请求。如果不能,将请求转交ASP.NET,这会激活另一个线程处理请求。ASP.NET尝试从它自己的缓存中响应请求,如果不能,再生成输出。结果会发送给第三个线程,再发送给浏览器。

    这意味着,如果可以从内核缓存中提供文件,可以节省三个线程切换和切换到用户模式的开销。这使得从内核缓存中提供文件非常快。IIS 7输出缓存需要一个线程切换和切换到用户模式,但仍然要比ASP.NET缓存快。

    缓存依赖,不是依赖于时间

    依赖于文件内容 CacheDependency cDep = new CacheDependency(filePath);
    依赖于数据库内容(轮询机制/通知机制)(不讲)
    一:轮询机制 –fw主动到数据库检查数据是否改变
    1.使用C:WINDOWSMicrosoft.NETFrameworkv2.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");

    缓存依赖文件
    if (Cache["time"] == null)
    {
    Cache.Insert("time", DateTime.Now, new System.Web.Caching.CacheDependency(Request.MapPath("~/TextFile1.txt")));
    }
    Response.Write(Cache["time"]);

    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);

    if (Cache["Time"] == null)
    {
    Cache.Insert("Time", DateTime.Now, new System.Web.Caching.CacheDependency(Server.MapPath("userfile.txt")));
    }
    Response.Write(Cache["Time"].ToString());

    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>

    依赖数据库改变,数据库缓存依赖
    C:WindowsMicrosoft.NETFrameworkv4.0.30319aspnet_regsql.exe
    1、数据库缓存依赖
    -S服务器名称 -E集成身份验证 -ed启动 -d数据库名称 -et指定缓冲依赖的表名 -t表名
    在vs2010的命令提示符中运行(切换到aspnet_regsql.exe所在的目录)
    aspnet_regsql -S steve-pc -E -ed -d apsxDb -et -t TblComments

    缓存依赖禁用该数据库
    aspnet_regsql -S steve-pc -E -dd -d apsxDb

    2、依赖于数据库的web.config配置
    <system.web>
    <caching>
    <sqlCacheDependency enabled="true" pollTime="500">
    <databases>
    <add name="ccdb_msdb" connectionStringName="mssqlserver_cache"/>
    </databases>
    </sqlCacheDependency>
    </caching>
    </system.web>
    <!--
    pollTime, 可选的 Int32 属性。
    设置 SqlCacheDependency 类实例轮询数据库表更改的频率。 此值对应于连续两次轮询之间的毫秒数。不能将其设置为小于 500 毫秒的值。默认值为 1 分钟。
    -->

    3、
    System.Web.Caching.SqlCacheDependency dep = new System.Web.Caching.SqlCacheDependency("ccdb_msdb", "NewPerson");
    Cache.Insert("list", list, dep, System.Web.Caching.Cache.NoAbsoluteExpiration, System.Web.Caching.Cache.NoSlidingExpiration);

    缓存(笔记)
    -》需求:当频繁使用某个数据时,总是从源来获取,既浪费服务器资源,又浪费浏览者时间
    将这些数据直接存到服务器内存中,用的时候直接获取
    -》应用场景:使用频繁,改变小,读取速度慢
    -》Cache对象是Page对象的一个属性,类型为键值对集合
    写:Cache["键"]=值
    读:Cache["键"]返回值
    -》过期时间:缓存会一直存在于服务器中,直到应用程序关闭
    使用Cache.Insert(键,值,null,绝对过期时间,滑动过期时间)来设置
    如果使用绝对过期时间,则将滑动过期时间设置为TimeSpan.Zero
    如果使用滑动过期时间,则将绝对过期时间设置为DataTime.MaxValue
    -》页面缓存
    如果页面被缓存,执行到第11、12事件间,会直接获取对象,后续处理不再执行
    可以为页面设置缓存依赖,指令:<%@OutputCache Duration="8" VaryByParam="缓存依据" />
    VaryByParam表示缓存依据,值为:none,*,参数名称
    多个参数时,可以使用分号";"进行分隔
    Duration表示缓存时间,单位为秒
    示例:在页面上输出当前时间,刷新查看是否每次都执行
    -》控件缓存:对于数据源控件,可以使用缓存功能
    EnableCaching="true"
    CacheDuration="5"
    CacheExpirationPolicy="Sliding"
    -》静态页面不被.net处理,如果希望缓存,可以在iis中进行设置
    点击缓存-》添加,添加扩展名,勾选“用户模块”、“内核模块”
    可以分别设置缓存时间
    -》缓存依赖:除了以时间的方式可以让缓存过期之外,还可以依赖于文件、数据库,相关设置参考ppt操作一遍即可

    WriteCache.aspx

     1 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WriteCache.aspx.cs" Inherits="t2_Cache.WriteCache" %>
     2 
     3 <!DOCTYPE html>
     4 
     5 <html xmlns="http://www.w3.org/1999/xhtml">
     6 <head runat="server">
     7     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
     8     <title></title>
     9 </head>
    10 <body>
    11     <form id="form1" runat="server">
    12         <div>
    13 
    14             <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Write" />
    15             <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
    16             <br />
    17             <a href="ReadCache.aspx">ReadCache.aspx</a>
    18         </div>
    19     </form>
    20 </body>
    21 </html>

    WriteCache.aspx.cs

     1     public partial class WriteCache : System.Web.UI.Page
     2     {
     3         protected void Page_Load(object sender, EventArgs e)
     4         {
     5 
     6         }
     7 
     8         protected void Button1_Click(object sender, EventArgs e)
     9         {
    10             //Cache.Insert("xlb",TextBox1.Text,null,new DateTime(2015,1,1), TimeSpan.Zero);
    11 
    12             Cache.Insert("xlb", TextBox1.Text, null, DateTime.MaxValue, TimeSpan.FromSeconds(10));
    13         }
    14     }

    ReadCache.aspx

     1 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ReadCache.aspx.cs" Inherits="t2_Cache.ReadCache" %>
     2 
     3 <!DOCTYPE html>
     4 
     5 <html xmlns="http://www.w3.org/1999/xhtml">
     6 <head runat="server">
     7     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
     8     <title></title>
     9 </head>
    10 <body>
    11     <form id="form1" runat="server">
    12         <div>
    13             <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Read" />
    14             <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
    15         </div>
    16     </form>
    17 </body>
    18 </html>

    ReadCache.aspx.cs

     1     public partial class ReadCache : System.Web.UI.Page
     2     {
     3         protected void Page_Load(object sender, EventArgs e)
     4         {
     5 
     6         }
     7 
     8         protected void Button1_Click(object sender, EventArgs e)
     9         {
    10             Label1.Text = Cache["xlb"].ToString();
    11         }
    12     }

    PageCache.aspx(页面缓存)

     1 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="PageCache.aspx.cs" Inherits="t2_Cache.PageCache" %>
     2 
     3 <%@ OutputCache Duration="10" VaryByParam="*" %>
     4 <!DOCTYPE html>
     5 
     6 <html xmlns="http://www.w3.org/1999/xhtml">
     7 <head runat="server">
     8     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
     9     <title></title>
    10 </head>
    11 <body>
    12     <form id="form1" runat="server">
    13         <div>
    14             <%=DateTime.Now.ToString() %>
    15             <hr />
    16             <a href="?id=1">id=1</a>
    17             <a href="?id=2">id=2</a>
    18             <a href="?id=1&page=1">id=1&page=1</a>
    19             <a href="?id=1&page=2">id=1&page=2</a>
    20         </div>
    21     </form>
    22 </body>
    23 </html>

    ControllCache.aspx(服务器控件缓存)

     1 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ControllCache.aspx.cs" Inherits="t2_Cache.ControllCache" %>
     2 
     3 <!DOCTYPE html>
     4 
     5 <html xmlns="http://www.w3.org/1999/xhtml">
     6 <head runat="server">
     7     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
     8     <title></title>
     9 </head>
    10 <body>
    11     <form id="form1" runat="server">
    12         <div>
    13             <asp:Repeater ID="Repeater1" runat="server" DataSourceID="SqlDataSource1">
    14                 <ItemTemplate>
    15                     <%#Eval("ProvinceId") %>
    16                 </ItemTemplate>
    17             </asp:Repeater>
    18             <asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:web1ConnectionString %>" SelectCommand="SELECT * FROM [S_Province]" EnableCaching="True"></asp:SqlDataSource>
    19         </div>
    20     </form>
    21 </body>
    22 </html>
  • 相关阅读:
    PyCharm中的Console自动换行
    Jenkins 配置用户权限错误导致无法登录解决方案
    Jenkins进阶-用户权限管理(10)
    python3+Flask 链接MySQL 时,提示“No module named MYSQLdb”
    Mongo导出mongoexport和导入mongoimport介绍
    maven常用命令
    Git 的origin和master分析
    How to handle your webdriver exceptions
    Java中equals和==的区别
    Maven中-DskipTests和-Dmaven.test.skip=true的区别
  • 原文地址:https://www.cnblogs.com/ninghongkun/p/6361873.html
Copyright © 2020-2023  润新知