第一種方式:html
在ASP.NET中頁面緩存的使用方法很是的簡單,只須要在aspx頁的頂部加這樣一句聲明便可:web
<%@ OutputCache Duration="60" VaryByParam="none" %>算法
Duration sql
緩存的時間(秒)。這是必選屬性。若是未包含該屬性,將出現分析器錯誤。數據庫
若是不加<%@ OutputCache Duration="60" VaryByParam="none" %>,每次刷新頁面上的時間每次都是在變。而加了緩存聲明之後,每次刷新頁面的時間並不變化,60秒後才變化一次,說明數據被緩存了60秒。編程
第二種方式:後端
protected void Page_Load(object sender, EventArgs e) {
Bind();
}
public void Bind()
{
DataTable dt = new DataTable();
if (this.Cache["Keys"] == null)
{
string connstring = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
SqlConnection conn = new SqlConnection(connstring);
conn.Open();
string sql = "select top 100000 * from SF_InstanceActivity";
SqlDataAdapter da = new SqlDataAdapter(sql, conn);
da.Fill(dt);
conn.Close();
// Go get the data from the database
this.Cache.Insert("Keys", dt, null, DateTime.Now.AddHours(2), TimeSpan.Zero);
}
else
{
dt = this.Cache["Keys"] as DataTable;
}
ASPxGridView1.DataSource = dt;
ASPxGridView1.DataBind();
}api
上例首先檢查具備Keys鍵的項是否在緩存中。若是不在,就從後端數據庫檢索一個ADO.NET DataTable,並使用Insert方法把它放到緩存中。本例使用的是Insert的一個重載版本,它容許爲緩存對象指定一個絕對過時時間(2小 時),而不是指定一個週期性的過時。相反,若是緩存中已經有這個項,就將其取回,並使用As表達式,將其強制轉換回一個DataTable。
對 ADO.NET檢索到的數據進行緩存時,注意既可像上例那樣緩存DataTable對象,也可緩存整個DataSet對象,由於兩種對象都同任何數據源完 全地斷開,不會保持數據庫鏈接。對數據讀取器(好比SqlDataReader)進行緩存彷佛更好一些,由於它們只使用一次(它們是「只進」的讀取器), 並且在打開的狀況下將一直佔據一個數據庫鏈接。
ASP.NET緩存引擎強大的靈活性和功能使其成爲建立高性能ASP.NET應用程序時最重要的特性之一。根據本文提供的基本信息,您可在本身的應用程序輕鬆引入緩存引擎功能。瀏覽器
轉載來自:http://www.cnblogs.com/Fooo/archive/2011/07/08/2100733.html緩存
系統緩存全解析1:系統緩存的概述
有時候總聽到網友說網站運行好慢,不知如何是好;有時候也總見到一些朋友寫的網站功能看起來很是好,但訪問性能卻極其的差。沒有「勤儉節約」的意識,勢必會形成「鋪張浪費」。如何應對這種狀況,充分利用系統緩存則是首要之道。
系統緩存有什麼好處呢?舉個簡單的例子,你想經過網頁查詢某些數據,而這些數據並不是實時變化,或者變化的時間是有期限的。例如查詢一些歷史數據。那麼每一個 用戶每次查的數據都是同樣的。若是不設置緩存,ASP.NET也會根據每一個用戶的請求重複查詢n次,這就增長了沒必要要的開銷。因此,可能的狀況下儘可能使用 緩存,從內存中返回數據的速度始終比去數據庫查的速度快,於是能夠大大提供應用程序的性能。畢竟如今內存很是便宜,用空間換取時間效率應該是很是划算的。 尤爲是對耗時比較長的、須要創建網絡連接的數據庫查詢操做等。
緩存功能是大型網站設計一個很重要的部分。由數據庫驅動的Web應用程序,若是須要改善其性能,最好的方法是使用緩存功能。
15.4.1 緩存的分類
從分佈上來看,咱們能夠歸納爲客戶端緩存和服務器端緩存。如圖15-1所示:
圖15-1 緩存的分類
客戶端緩存—— 這點你們都有直觀的印象。好比你去一個新的網站,第一次可能要花一陣子時間才能載入整個頁面。而之後再去呢,時間就會大大的縮短,緣由就在於這個客戶端緩 存。如今的瀏覽器都比較智能,它會在客戶機器的硬盤上保留許多靜態的文件,好比各類gif,jpeg文件等等。等之後再去的時候,它會盡可能使用本地緩存裏 面的文件。只有服務器端的文件更新了,或是緩存裏面的文件過時了,它纔會再次從服務器端下載這些東西。不少時候是IE替咱們作了這件事情。
服務器端緩存—— 有些東西無法或是不宜在客戶端緩存,那麼咱們只好在服務器端想一想辦法了。服務器端緩存從性質上看,又能夠分爲兩種。
(1)靜態文件緩存
好多頁面是靜態的,不多改動,那麼這種文件最適於做靜態緩存。如今的IIS 6.0這部份內容是直接存放在Kernel的內存中,由HTTP.SYS直接管理。因爲它在Kernel Space,因此它的性能很是的高。用戶的請求若是在緩存裏面,那麼HTTP.SYS直接將內容發送到network driver上去,不須要像之前那樣從IIS的User space的內存copy到Kernel中,而後再發送到TCP/IP stack上。Kernel level cache幾乎是如今高性能Web server的一個必不可少的特性。
(2)動態緩存
動態緩存是比較有難度的。由於你在緩存的時候要時刻注意一個問題,那就是緩存的內容是否是已通過時了。由於內容過期了可能會有很嚴重的後果。好比網上買賣 股票的網站。你給別人提供的價格是過期的,那人家非砍了你不可。緩存如何發現本身是否是過期就是一個很是複雜的問題。
在ASP.NET中,常見的動態緩存主要有如下幾種手段:
Ø 傳統緩存方式
Ø 頁面輸出緩存。
Ø 頁面局部緩存。
Ø 利用.NET提供的System.Web.Caching 緩存。
Ø 緩存依賴。
15.4.2 傳統緩存方式
好比將可重複利用的東西放到Application或是Session中去保存。
Session["Style"] = val;
Application["Count"] = 0;
===============================================================================
系統緩存全解析2:頁面輸出緩存
頁面輸出緩存是最爲 簡單的緩存機制,該機制將整個ASP.NET頁面內容保存在服務器內存中。當用戶請求該頁面時,系統從內存中輸出相關數據,直到緩存數據過時。在這個過程 中,緩存內容直接發送給用戶,而沒必要再次通過頁面處理生命週期。一般狀況下,頁面輸出緩存對於那些包含不須要常常修改內容的,但須要大量處理才能編譯完成 的頁面特別有用。須要讀者注意的是,頁面輸出緩存是將頁面所有內容都保存在內存中,並用於完成客戶端請求。
在ASP.NET中頁面緩存的使用方法很是的簡單,只須要在aspx頁的頂部加這樣一句聲明便可:
<%@ OutputCache Duration="60" VaryByParam="none" %> |
Duration
緩存的時間(秒)。這是必選屬性。若是未包含該屬性,將出現分析器錯誤。
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="CacheWebApp._16_4_3.WebForm1" %> <%@ OutputCache Duration="60" VaryByParam="none" %> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>頁面緩存示例</title> </head> <body> <form id="form1" runat="server"> <div> <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label> </div> </form> </body>
</html> |
後臺代碼:
protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { Label1.Text = DateTime.Now.ToString(); }
} |
若是不加<%@ OutputCache Duration="60" VaryByParam="none" %>,每次刷新頁面上的時間每次都是在變。而加了緩存聲明之後,每次刷新頁面的時間並不變化,60秒後才變化一次,說明數據被緩存了60秒。
VaryByParam
是指頁面根據使用 POST 或 GET 發送的名稱/值對(參數)來更新緩存的內容,多個參數用分號隔開。若是不但願根據任何參數來改變緩存內容,請將值設置爲 none。若是但願經過全部的參數值改變都更新緩存,請將屬性設置爲星號 (*)。
例如: http://localhost:1165/16-4-3/WebForm1.aspx?p=1
則能夠在WebForm1.aspx頁面頭部聲明緩存:<%@ OutputCache Duration="60" VaryByParam="p" %>
以上代碼設置頁面緩存時間是60秒,並根據p參數的值來更新緩存,即p的值發生變化才更新緩存。
若是一直是WebForm1.aspx?p=1訪問該頁,則頁面會緩存當前數據,當p=2時又會執行後臺代碼更新緩存內容。
若是有多個參數時,如:http://localhost:1165/16-4-3/WebForm1.aspx?p=1&n=1
能夠這樣聲明:<%@ OutputCache Duration="60" VaryByParam="p;n" %>
除此以外,@OutputCache 還有一些其餘的屬性。@OutputCache指令中的屬性參數描述以下:
<%@ OutputCache Duration="#ofseconds" Location="Any | Client | Downstream | Server | None | ServerAndClient " Shared="True | False" VaryByControl="controlname" VaryByCustom="browser | customstring" VaryByHeader="headers" VaryByParam="parametername" CacheProfile="cache profile name | ''" NoStore="true | false" SqlDependency="database/table name pair | CommandNotification"
%> |
CacheProfile
用於調用Web.config配置文件中設置的緩存時間。這是可選屬性,默認值爲空字符 ("")。
例如:
在Web.config中加入配置:
<system.web> <caching> <outputCacheSettings> <outputCacheProfiles> <addname="CacheTest" duration="50" /> </outputCacheProfiles> </outputCacheSettings>
</caching>
</system.web>
|
頁面中聲明:
<%@ OutputCache CacheProfile="CacheTest" VaryByParam="none" %> |
注意: 包含在用戶控件(.ascx 文件)中的 @ OutputCache 指令不支持此屬性。在頁中指定此屬性時,屬性值必須與 outputCacheSettings 節下面的 outputCacheProfiles 元素中的一個可用項的名稱匹配。若是此名稱與配置文件項不匹配,將引起異常。 |
若是每一個頁面的緩存時間相同,則不須要每一個頁面設置,而是經過統一一個地方控制,這樣就能夠更好的統一控制全部頁面的緩存時間。若是想改變緩存時間,只須要改一下web.config的配置信息便可,而不用每一個頁面去修改。
VaryByControl
經過用戶控件文件中包含的服務器控件來改變緩存(值是控件ID,多控件用分號隔開)。
在 ASP.NET 頁和用戶控件上使用 @ OutputCache 指令時,須要該屬性或 VaryByParam 屬性。
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm2.aspx.cs" Inherits="CacheWebApp._16_4_3.WebForm2" %> <%@ OutputCache Duration="60" VaryByParam="none" VaryByControl="DropDownList1" %>
<html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>根據控件頁面緩存</title> </head> <body> <form id="form1" runat="server"> <div> <%=DateTime.Now %> <br> <asp:DropDownList ID="DropDownList1" runat="server"> <asp:ListItem>beijing</asp:ListItem> <asp:ListItem>shanghai</asp:ListItem> <asp:ListItem>guangzhou</asp:ListItem> </asp:DropDownList> <asp:Button ID="Button1" runat="server" Text="提交" /> </div> </form> </body>
</html> |
以上代碼設置緩存有效期是60秒,而且頁面不隨任何GET或POST參數改變(即便不使用VaryByParam屬性, 可是仍然須要在@ OutputControl指令中顯式聲明該屬性)。若是用戶控件中包含ID屬性爲「DropDownList1」的服務器控件(例以下拉框控件),那麼 緩存將根據該控件的變化來更新頁面數據。
頁面輸出緩存API
Response類的Cache屬性用於獲取頁面緩存策略。該方式的核心是調用 System.Web.HttpCachePolicy。該類主要包含用於設置緩存特定的HTTP標頭的方法和用於控制ASP.NET頁面輸出緩存的方 法。與.NET Framework 1.x中的HttpCachePolicy類相比,.NET Framework 2.0中的HttpCachePolicy類獲得了擴充和發展。主要是增長了一些重要方法,例如,SetOmitVarStar方法等。因爲 HttpCachePolicy類方法衆多,下面簡要說明幾個經常使用方法。
SetExpires方法
用於設置緩存過時的絕對時間。它的參數是一個DataTime類的實例,表示過時的絕對時間。
protected void Page_Load(object sender, EventArgs e) { // 經過API設置緩存 //至關於@OutputCache指令中的Duration屬性 Response.Cache.SetExpires(DateTime.Now.AddSeconds(10)); Response.Cache.SetExpires(DateTime.Parse("6:00:00PM")); } |
如上代碼,第一行代碼表示輸出緩存時間是60秒,而且頁面不隨任何GET或POST參數改變,等同於「<%@ OutputCache Duration="60" VaryByParam="none" %>」。第二行代碼設置緩存過時的絕對時間是當日下午6時整。
SetLastModified方法
用於設置頁面的Last-Modified HTTP標頭。Last-Modified HTTP標頭表示頁面上次修改時間,緩存將依靠它來進行計時。若是違反了緩存限制層次結構,此方法將失敗。該方法的參數是一個DataTime類的實例。
SetSlidingExpiration方法
該方法將緩存過時從絕對時間設置爲可調時間。其參數是一個布爾值。當參數爲true時,Cache-Control HTTP標頭將隨每一個響應而更新。此過時模式與相對於當前時間將過時標頭添加到全部輸出集的IIS配置選項相同。當參數爲False時,將保留該設置,且 任何啓用可調整過時的嘗試都將靜態失敗。此方法不直接映射到HTTP標頭。它由後續模塊或輔助請求來設置源服務器緩存策略。
SetOmitVaryStar方法
ASP.NET 2.0新增的方法。用於指定在按參數進行區分時,響應是否應該包含vary:*標頭。方法參數是一個布爾值,若要指示HttpCachePolicy不對其VaryByHeaders屬性使用*值,則爲true;不然爲false。
SetCacheability方法
用於設置頁面的Cache-Control HTTP標頭。該標頭用於控制在網絡上緩存文檔的方式。該方法有兩種重載方式,所不一樣的是參數。一種重載方法的參數是HttpCacheability枚 舉值,包括NoCache、Private、Public、Server、ServerAndNoCache和ServerAndPrivate(有關這 些枚舉值的定義,可參考MSDN)。另外一種方法的參數有兩個,一個參數是HttpCacheability枚舉值,另外一個參數是字符串,表示添加到標頭的 緩存控制擴展。須要注意的是,僅當與Private或NoCache指令一塊兒使用時,字段擴展名纔有效。若是組合不兼容的指令和擴展,則此方法將引起無效 參數異常。
===============================================================================
系統緩存全解析3:頁面局部緩存
有時緩存整個頁面是不現實的,由於頁的某些部分可能在每次請求時都須要變化。在這些狀況下,只能緩存頁的一部分。顧名思義,頁面部分緩存是將頁面部份內容保存在內存中以便響應用戶請求,而頁面其餘部份內容則爲動態內容。頁面部分緩存的實現包括兩種方式:控件緩存和替換後緩存。
1. 控件緩存(也稱爲片斷緩存)
這種方式容許將須要緩存的信息包含在一個用戶控件內,而後,將該用戶控件標記爲可緩存的,以此來緩存頁面輸出的部份內容。該選項容許緩存頁面中的特定內 容,而沒有緩存整個頁面,所以,每次都需從新建立整個頁。例如,若是要建立一個顯示大量動態內容(如股票信息)的頁,其中有些部分爲靜態內容(如每週總 結),這時能夠將靜態部分放在用戶控件中,並容許緩存這些內容。
在ASP.NET中,提供了UserControl這種用戶控件的功能。一個頁面能夠經過多個UserControl來組成。只須要在某個或某幾個UserControl裏設置緩存。
例如:
那麼能夠在WebUserControl1.ascx的頁頭代碼中添加聲明語句:
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="WebUserControl1.ascx.cs" Inherits="CacheWebApp._16_4_5.WebUserControl1" %> <%@ OutputCache Duration="60" VaryByParam="none" %>
<%=DateTime.Now %> |
調用該控件的頁面WebForm1.aspx代碼:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="CacheWebApp._16_4_5.WebForm1" %> <%@ Register src="WebUserControl1.ascx" tagname="WebUserControl1" tagprefix="uc1" %> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>控件緩存</title> </head> <body> <form id="form1" runat="server"> <div> 頁面的:<%=DateTime.Now %> </div> <div> 控件的:<uc1:WebUserControl1 ID="WebUserControl11" runat="server" /> </div> </form> </body>
</html> |
這時候刷新WebForm1.aspx頁面時,頁面的時間每次刷新都變化,而用戶控件中的時間數據倒是60秒才變化一次,說明對頁面的「局部」控件實現了緩存,而整個頁面不受影響。
2. 緩存後替換
與控件緩存正好相反。它對整個頁面進行緩存,可是頁中的某些片斷是動態的,所以不會緩存這些片斷。ASP.NET頁面中既包含靜態內容,又包含基於數據庫 數據的動態內容。靜態內容一般不會發生變化。所以,對靜態內容實現數據緩存是很是必要的。然而,那些基於數據的動態內容,則不一樣。數據庫中的數據可能每時 每刻都發生變化,所以,若是對動態內容也實現緩存,可能形成數據不能及時更新的問題。對此問題若是使用前文所述的控件緩存方法,顯然不切實際,並且實現起 來很繁瑣,易於發生錯誤。
如何實現緩存頁面的大部份內容,而不緩存頁面中的局部某些片斷。ASP.NET 2.0提供了緩存後替換功能。實現該項功能可經過如下三種方法:
一是以聲明方式使用Substitution控件,
二是以編程方式使用Substitution控件API,
三是以隱式方式使用控件。
前兩種方法的核心是Substitution控件,本節將重點介紹該控件,第三種方法僅專一於控件內置支持的緩存後替換功能,本節僅作簡要說明。
(1) Substitution控件應用
爲提升應用程序性能,可能會緩存整個ASP.NET頁面,同時,可能須要根據每一個請求來更新頁面上特定的部分。例如,可能要緩存頁面的很大一部分,須要動 態更新該頁上與時間或者用戶高度相關的信息。在這種狀況下,推薦使用Substitution控件。Substitution控件可以指定頁面輸出緩存中 須要以動態內容替換該控件的部分,即容許對整頁面進行輸出緩存,而後,使用Substitution控件指定頁中免於緩存的部分。須要緩存的區域只執行一次,而後從緩存讀取,直至該緩存項到期或被清除。動態區域,也就是Substitution控件指定的部分,在每次請求頁面時都執行。Substitution控件提供了一種緩存部分頁面的簡化解決方案。
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm2.aspx.cs" Inherits="CacheWebApp._16_4_5.WebForm2" %> <%@ OutputCache Duration="60" VaryByParam="none" %> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>緩存後替換示例</title> </head> <body> <form id="form1" runat="server"> <div> 頁面緩存的時間:<%= DateTime.Now.ToString() %> </div> <div> 真實(替換)的時間:<asp:Substitution ID="Substitution1" runat="server" MethodName="getCurrentTime" /> </div> </form> </body>
</html> |
頁面後臺代碼:
public partial class WebForm2 : System.Web.UI.Page { public static string getCurrentTime(HttpContext context) { return DateTime.Now.ToString(); } } |
如上代碼所示,Substitution控件有一個重要屬性:MethodName。該屬性用於獲取或者設置當Substitution控件執行時爲回調而調用的方法名稱。該方法比較特殊,必須符合如下3條標準:
在運行狀況下,Substitution控件將自動調用MethodName屬性所定義的方法。該方法返回的字符串即爲要在頁面中的Substitution控件的位置上顯示的內容。 若是頁面設置了緩存所有輸出,那麼在第一次請求時,該頁將運行並緩存其輸出。對於後續的請求,將經過緩存來完成,該頁上的其餘代碼不會再運行。但 Substitution控件及其有關方法則在每次請求時都執行,而且自動更新該控件所表示的動態內容,這樣就實現了總體緩存,局部變化的替換效果。
如上代碼所示,在代碼頭部經過@ OutputCache指令設置頁面輸出緩存過時時間爲5秒,這意味着整個頁面數據都應用了緩存功能。所以,「頁面緩存的時間」所顯示的時間值來自於數據 緩存。這個時間值不會隨着刷新頁面而變化,僅當緩存過時時纔會發生更新。Substitution控件的MethodName屬性值爲 getCurrentTime。該控件顯示的內容來自於getCurrentTime方法的返回值。尤其重要的是,雖然頁面設置了輸出緩存功能,可是每當 頁面刷新時,ASP.NET執行引擎仍然要從新執行Substitution控件,並將MethodName屬性值指定的方法返回值顯示在頁面上,所以, 顯示的是當前最新時間。
示例效果,如圖15-2所示:
圖15-2 緩存後替換
隨着頁面的刷新,真實時間在變,而頁面緩存的時間在指定的緩存時間內始終不變。
注意: l Substitution控件沒法訪問頁上的其餘控件,也就是說,沒法檢查或更改其餘控件的值。可是,代碼確實可使用傳遞給它的參數來訪問當前頁上下文。 l 在緩存頁包含的用戶控件中能夠包含Substitution控件。可是,在輸出緩存用戶控件中不能放置Substitution控件。 l Substitution控件不會呈現任何標記,其位置所顯示內容徹底取決於所定義方法的返回字符串。 |
(2) Substitution控件API應用
上一小節介紹了以聲明方式使用Substitution控件實現緩存後替換的應用。本節說明另外一種實現方法。該方法的核心是以編程方式利用Substitution控件API實現緩存後替換,相對於以聲明方式使用Substitution控件的方法具備更強靈活性。
經過爲Substitution指定回調方法,實現和聲明一樣的效果。Substitution的回調方法必須是
HttpResponseSubstitutionCallback委託定義的方法,它有兩個特徵:
l 一是返回值必須是String,
l 二是參數有且僅有一個,而且是HttpContext類型。
當須要以編程方式,爲緩存的輸出響應動態生成指定的響應區域時,能夠在頁面代碼中將某個方法(即回調方法)的名稱做爲參 數(HttpResponseSubstitutionCallback)傳遞給Substitution。這樣Substitution就可以使用回調 方法,並將回調方法的返回值做爲給定位置的替代內容顯示出來。
須要注意的是,回調方法必須是線程安全的,能夠是做爲容器的頁面或者用戶控件中的靜態方法,也能夠是其餘任意對象上的靜態方法或實例方法。
下面演示一個以編程方式將 Substitution 控件添加到輸出緩存網頁。與(1)Substitution控件應用所示的示例完成一樣功能。不一樣的是實現方式。
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm3.aspx.cs" Inherits="CacheWebApp._16_4_5.WebForm3" %> <%@ OutputCache Duration="60" VaryByParam="none" %> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title>緩存後替換-Substitution控件API應用</title> </head> <body> <form id="form1" runat="server"> <div> 頁面緩存的時間:<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label> </div> <div> 真實(緩存替換)的時間: <asp:PlaceHolder ID="PlaceHolder1" runat="Server"></asp:PlaceHolder> </div> </form> </body>
</html> |
頁面後臺CS代碼:
protected void Page_Load(object sender, EventArgs e) { //建立一個Substitution Substitution Substitution1 = new Substitution(); //指定調用的回調方法名 Substitution1.MethodName = "GetCurrentDateTime"; PlaceHolder1.Controls.Add(Substitution1);
Label1.Text=DateTime.Now.ToString(); } public static string GetCurrentDateTime(HttpContext context) { return DateTime.Now.ToString(); } |
如上代碼所示,頁面使用@ OutputCache指令設置了輸出緩存功能,其配置數據緩存過時時間爲60秒。然而,頁面其餘內容都被緩存,經過Substitution調用的回調方法顯示的內容是不被緩存的。
===============================================================================
系統緩存全解析4:應用程序數據緩存
System.Web.Caching 命名空間提供用於緩存服務器上經常使用數據的類。此命名空間包括 Cache 類,該類是一個字典,您能夠在其中存儲任意數據對象,如哈希表和數據集。它還爲這些對象提供了失效功能,併爲您提供了添加和移除這些對象的方法。您還能夠 添加依賴於其餘文件或緩存項的對象,並在從 Cache 對象中移除對象時執行回調以通知應用程序。
/// <summary> /// 獲取當前應用程序指定CacheKey的Cache對象值 /// </summary> /// <param name="CacheKey">索引鍵值</param> /// <returns>返回緩存對象</returns> public static object GetCache(string CacheKey) { System.Web.Caching.Cache objCache = HttpRuntime.Cache; return objCache[CacheKey]; } /// <summary> /// 設置當前應用程序指定CacheKey的Cache對象值 /// </summary> /// <param name="CacheKey">索引鍵值</param> /// <param name="objObject">緩存對象</param> public static void SetCache(string CacheKey, object objObject) { System.Web.Caching.Cache objCache = HttpRuntime.Cache; objCache.Insert(CacheKey, objObject); } /// <summary> /// 設置當前應用程序指定CacheKey的Cache對象值 /// </summary> /// <param name="CacheKey">索引鍵值</param> /// <param name="objObject">緩存對象</param> /// <param name="absoluteExpiration">絕對過時時間</param> /// <param name="slidingExpiration">最後一次訪問所插入對象時與該對象過時時之間的時間間隔</param> public static void SetCache(string CacheKey, object objObject, DateTime absoluteExpiration, TimeSpan slidingExpiration) { System.Web.Caching.Cache objCache = HttpRuntime.Cache; objCache.Insert(CacheKey, objObject, null, absoluteExpiration, slidingExpiration); } protected void Page_Load(object sender, EventArgs e) { string CacheKey = "cachetest"; object objModel = GetCache(CacheKey);//從緩存中獲取 if (objModel == null)//緩存裏沒有 { objModel = DateTime.Now;//把當前時間進行緩存 if (objModel != null) { int CacheTime = 30;//緩存時間30秒 SetCache(CacheKey, objModel, DateTime.Now.AddSeconds(CacheTime), TimeSpan.Zero);//寫入緩存 } } Label1.Text = objModel.ToString(); } |
以上幾種方法都很好的解決了數據緩存的問題,但由一個最大的問題是當數據發生變化了,而緩存裏仍是過時的數據,只有等緩存過時後纔會從新獲取最新的數據, 這樣的話,不少時候用戶獲取的數據都是和實際數據不一致的過時數據。這一樣給用戶形成了比較大的麻煩,怎麼辦呢?接着往下看。
===============================================================================
系統緩存全解析5:文件緩存依賴
這種策略讓緩存依賴於一個指定的文件,經過改變文件的更新日期來清除緩存。
/// <summary> /// 獲取當前應用程序指定CacheKey的Cache對象值 /// </summary> /// <param name="CacheKey">索引鍵值</param> /// <returns>返回緩存對象</returns> public static object GetCache(string CacheKey) { System.Web.Caching.Cache objCache = HttpRuntime.Cache; return objCache[CacheKey]; } /// <summary> /// 設置以緩存依賴的方式緩存數據 /// </summary> /// <param name="CacheKey">索引鍵值</param> /// <param name="objObject">緩存對象</param> /// <param name="cacheDepen">依賴對象</param> public static void SetCache(string CacheKey, object objObject, System.Web.Caching.CacheDependency dep) { System.Web.Caching.Cache objCache = HttpRuntime.Cache; objCache.Insert( CacheKey, objObject, dep, System.Web.Caching.Cache.NoAbsoluteExpiration, //從不過時 System.Web.Caching.Cache.NoSlidingExpiration, //禁用可調過時 System.Web.Caching.CacheItemPriority.Default, null); } protected void Page_Load(object sender, EventArgs e) { string CacheKey = "cachetest"; object objModel = GetCache(CacheKey);//從緩存中獲取 if (objModel == null) //緩存裏沒有 { objModel = DateTime.Now;//把當前時間進行緩存 if (objModel != null) { //依賴 C:\\test.txt 文件的變化來更新緩存 System.Web.Caching.CacheDependency dep = new System.Web.Caching.CacheDependency("C:\\test.txt"); SetCache(CacheKey, objModel, dep);//寫入緩存 } }
Label1.Text = objModel.ToString(); } |
當咱們改變test.txt的內容時,緩存會自動更新。這種方式很是適合讀取配置文件的緩存處理。若是配置文件不變化,就一直讀取緩存的信息,一旦配置發生變化,自動更新同步緩存的數據。
這種方式的缺點是,若是緩存的數據比較多,相關的依賴文件比較鬆散,對管理這些依賴文件有必定的麻煩。對於負載均衡環境下,還須要同時更新多臺Web服務器下的緩存文件,若是多個Web應用中的緩存依賴於同一個共享的文件,可能會省掉這個麻煩。
===============================================================================
系統緩存全解析6:數據庫緩存依賴
更多的時候,咱們的服務器性能損耗仍是在查詢數據庫的時候,因此對數據庫的緩存仍是顯得特別重要,上面幾種方式均可以實現部分數據緩存功能。但問題是咱們 的數據有時候是在變化的,這樣用戶可能在緩存期間查詢的數據就是老的數據,從而致使數據的不一致。那有沒有辦法作到,數據若是不變化,用戶就一直從緩存中 取數據,一旦數據變化,系統能自動更新緩存中的數據,從而讓用戶獲得更好的用戶體驗。
答案是確定的!.NET已經爲咱們提供了這樣一種很是好的解決方法:SqlCacheDependency數據庫緩存依賴。
實現步驟:
下面就讓咱們看一下如何實現數據庫緩存依賴功能:
第一步: 修改web.config,讓項目啓用SqlCacheDependency 。
將下列代碼加入web.config的<system.web>節:
<?xml version="1.0"?> <configuration> <appSettings/> <connectionStrings> <addname="strcodematic" connectionString="data source=127.0.0.1;initial catalog=codematic;user id=sa;password=" providerName="System.Data.SqlClient" /> </connectionStrings> <system.web> <caching> <sqlCacheDependencyenabled="true" pollTime="6000"> <databases> <addname="codematic" connectionStringName="strcodematic" /> </databases> </sqlCacheDependency> </caching>
<compilation debug="true"> </compilation> <authentication mode="Windows"/> </system.web> </configuration>
|
這裏的connectionStringName指定了在<connectionStrings>中添加的某一個鏈接字符串。name則是爲該SqlCacheDependency起的名字,這個名字將在第3步中用到。
SqlCacheDependency類會自動完成對此配置節信息的讀取以創建和數據庫之間的聯繫。
注意: 在<databases>節的<add name="codematic" connectionStringName="strcodematic" />中的name屬性值必須和第三步的Page_Load代碼中System.Web.Caching.SqlCacheDependency("codematic", "P_Product");中的第一個參數(數據庫名稱)相一致。 |
第二步:執行下述命令,爲 數據庫啓用緩存依賴。
若是要配置SqlCacheDependency,則須要以命令行的方式執行。
aspnet_regsql.exe工具位於Windows\\Microsoft.NET\\Framework\\[版本]文件夾中。
aspnet_regsql -C "data source=127.0.0.1;initial catalog=codematic;user id=sa;password=" -ed -et -t "P_Product"
參數-C後面的字符串是鏈接字符串(請替換成本身所須要的值),
參數-t後面的字符串是數據表的名字。
運行結果如圖15-3所示:
圖15-3 啓用數據庫緩存依賴
命令執行後,在指定的數據庫中會多出一個AspNet_SqlCacheTablesForChangeNotification表。
注意: 要使得7.0或者2000版本以上的SQLServer支持SqlCacheDependency特性,須要對數據庫服務器執行相關的配置。 有兩種方法配置SQLServer: 一 使用aspnet_regsql命令行工具, 二 使用SqlCacheDependencyAdmin類。 例如: aspnet_regsql -S "server" -E -d "database" –ed 或者 aspnet_regsql -S "server" -E -d "database" -et -t "table" 如下是該工具的命令參數說明: -? 顯示該工具的幫助功能; -S 後接的參數爲數據庫服務器的名稱或者IP地址; -U 後接的參數爲數據庫的登錄用戶名; -P 後接的參數爲數據庫的登錄密碼; -E 使用當前登陸用戶的 Windows 集成認證進行身份驗證。 -d 後接參數爲對哪個數據庫採用SqlCacheDependency功能; -C 鏈接數據庫的鏈接字符串。若是您指定服務器(-S)和登陸(-U和-P,或 -E)信息,則此選項不是必需的,由於鏈接字符串已經包含這些信息。 -t 後接參數爲對哪個表採用SqlCacheDependency功能; -ed 容許對數據庫使用SqlCacheDependency功能; -dd 禁止對數據庫採用SqlCacheDependency功能; -et 容許對數據表採用SqlCacheDependency功能; -dt 禁止對數據表採用SqlCacheDependency功能; -lt 列出當前數據庫中有哪些表已經採用sqlcachedependency功能。 |
第三步:在代碼中使用緩存,併爲其設置SqlCacheDependency依賴:
/// <summary> /// 獲取當前應用程序指定CacheKey的Cache對象值 /// </summary> /// <param name="CacheKey">索引鍵值</param> /// <returns>返回緩存對象</returns> public static object GetCache(string CacheKey) { System.Web.Caching.Cache objCache = HttpRuntime.Cache; return objCache[CacheKey]; } /// <summary> /// 設置以緩存依賴的方式緩存數據 /// </summary> /// <param name="CacheKey">索引鍵值</param> /// <param name="objObject">緩存對象</param> /// <param name="cacheDepen">依賴對象</param> public static void SetCache(string CacheKey, object objObject, System.Web.Caching.CacheDependency dep) { System.Web.Caching.Cache objCache = HttpRuntime.Cache; objCache.Insert( CacheKey, objObject, dep, System.Web.Caching.Cache.NoAbsoluteExpiration,//從不過時 System.Web.Caching.Cache.NoSlidingExpiration,//禁用可調過時 System.Web.Caching.CacheItemPriority.Default, null); } protected void Page_Load(object sender, EventArgs e) { string CacheKey = "cachetest"; object objModel = GetCache(CacheKey);//從緩存中獲取 if (objModel == null)//緩存裏沒有 { objModel = GetData();//把當前時間進行緩存 if (objModel != null) { //依賴數據庫codematic中的P_Product表變化 來更新緩存 System.Web.Caching.SqlCacheDependency dep = new System.Web.Caching.SqlCacheDependency("codematic", "P_Product"); SetCache(CacheKey, objModel, dep);//寫入緩存 } }
GridView1.DataSource = (DataSet)objModel; GridView1.DataBind(); }
//查詢數據 private DataSet GetData() { string conString = "data source=127.0.0.1;initial catalog=codematic;user id=sa;password="; string strSQL = "SELECT * FROM P_Product"; SqlConnection myConnection = new SqlConnection(conString); DataSet ds = new DataSet(); myConnection.Open(); SqlDataAdapter adapter = new SqlDataAdapter(strSQL, myConnection); adapter.Fill(ds, "Product"); myConnection.Close(); return ds; } |
從以上代碼能夠看出,和文件依賴基本相同,只是在存放緩存SetCache時存入的依賴對象不一樣罷了。這裏用的是SqlCacheDependency。
其中,建立SqlCacheDependency的構造方法:
public SqlCacheDependency (string databaseEntryName,string tableName) |
l databaseEntryName :是在Web.config 文件的 caching 節的 sqlCacheDependency 的 databases 元素中定義的數據庫的名稱。
l tableName :與 SqlCacheDependency 關聯的數據庫表的名稱。
這樣,只有當P_Product表的內容發生變化時,查詢操做纔會從新查詢數據更新緩存的內容,能夠大大減小數據庫的重複查詢和提升系統的性能和運行效率。
===============================================================================
系統緩存全解析7:第三方分佈式緩存解決方案 Memcached和Cacheman
Memcached — 分佈式緩存系統
1.Memcached是什麼?
Memcached是高性能的,分佈式的內存對象緩存系統,用於在動態應用中減小數據庫負載,提高訪問速度。Memcached經過在內存裏維護一個統一 的巨大的hash表,它可以用來存儲各類格式的數據,包括圖像、視頻、文件以及數據庫檢索的結果等。Memcached由Danga Interactive最初爲了加速 LiveJournal網站訪問速度而開發的,後來被不少大型的網站採用。起初做者編寫它多是爲了提升動態網頁應用,爲了減輕數據庫檢索的壓力,來作的 這個緩存系統。它的緩存是一種分佈式的,也就是能夠容許不一樣主機上的多個用戶同時訪問這個緩存系統,這種方法不只解決了共享內存只能是單機的弊端, 同時也解決了數據庫檢索的壓力,最大的優勢是提升了訪問獲取數據的速度!基於memcached做者對分佈式cache的理解和解決方案。 memcached徹底能夠用到其餘地方 好比分佈式數據庫,分佈式計算等領域。Memcached將數據庫負載大幅度下降,更好的分配資源,更快速訪問。
2.Memcached工做機制
經過在內存中開闢一塊區域來維持一個大的hash表來加快頁面訪問速度,和數據庫是獨立的。可是目前主要用來緩存數據庫的數據。容許多個server經過 網絡造成一個大的hash,用戶沒必要關心數據存放在哪,只調用相關接口就可。存放在內存的數據經過LRU算法進行淘汰出內存。同時能夠經過刪除和設置失效 時間來淘汰存放在內存的數據。
如今一些.NET開發人員開始放棄ASP.NET內置的緩存機制,轉而使用Memcached——一種分佈式的內存緩存系統。當運行在單獨的Web服務器 上,你能夠很容易地清除一個已經確認被改變了的緩存。惋惜,ASP.NET沒有一個很好的方法來支持多服務器。每一個服務器上的緩存都對其餘緩存的改變一無 所知。
ASP.NET容許經過基於文件系統和數據庫表的觸發器來做廢一個緩存。然而,這也存在問題,好比數據庫觸發器須要使用昂貴的輪詢,以及觸發器自己冗長的編程。可是,咱們仍是有其餘的選擇的。
不像ASP.NET內置的緩存機制,Memcached是一個分佈式的緩存系統。任何Web服務器都能更新或刪除一個緩存項,而且全部其餘的服務器都能在 下次訪問這些緩存項的時候自動獲取到更新的內容。這是經過把這些緩存項存儲在一個或者多個緩存服務器上來實現的。每個緩存項都根據它的關鍵字的哈希值來 分配到一個服務器上。
表面看來,Memcached針對ASP.NET的API就像和內置的API同樣。這讓開發人員很容易地轉換到Memcached上,僅僅經過在代碼中查找和替換便可實現。
一個被推薦的解決方案是不根據緩存項的關鍵字來生成哈希鍵值。這將容許開發人員可以讓一個給定頁面中須要的全部緩存項,儘可能存放在同一個服務器上。惋惜, 基於數據保存的地方而不是基於緩存項自身的關鍵字來生成哈希鍵,很容易產生錯誤,須要仔細來實現(這個算法)。
Memcached是基於Linux運行的,你能夠在BSD的許可協議下使用Memcached。他也提供了針對C#的客戶端以及Perl、Python、PHP、Java和其餘語言的API:http://www.danga.com/memcached/apis.bml。還有一個Win32的移植版本(http://jehiah.cz/projects/memcached-win32/),可讓Memcached運行在非Linux的機器上。
Cacheman — .NET架構下的分佈式緩存項目
Cacheman聽說是由微軟旗下的 Popfly 項目組成員 Sriram Krishnan 的做品。是他用業餘時間開發的。最新的狀況是,微軟的 Popfly 網站已經「悄悄地」的作了更新,就是採用了 Krishnan 的 Cacheman,更新了緩存機制。該項緩存技術更新帶來的性能提高很是顯著,根據Popfly團隊中的 John Montgomery 的說法:加載一個已有的Mashup應用時,能夠帶來2到6倍的性能提高。
這些說法也獲得了 Krishnan 本人的確認。他提到這是Cacheman 的第一次的實際應用,並自豪的說 Cacheman 不費吹灰之力就拿下了 Popfly 的所有訪問量。
簡單介紹一下 Cacheman 這個項目。資料主要來源於 Krishnan的博客對Cacheman的介紹。
Cacheman是一個基於Windows平臺的快速分佈式哈希表。是由純託管代碼實現。中間擱置了有幾個月,直到最近纔開始從新上馬這個項目,很可能就是由於Popfly項目須要的緣故纔開始着手的。
Krishnan本人對 memcached 很感興趣,因而建立了 Cacheman。Cacheman上有不少 memcached 的影子,好比與memcached類似的文本通信協議。Cacheman的通信協議公開,任何人能夠根據本身偏心的語言環境寫客戶端。 Krishnan 在本身家用電腦(2.4GHz Intel Core 2 帶2GB內存)上進入測試,達到了每秒16000次左右的請求,而且仍是服務器與客戶端都是在同一臺服務器下完成的。
現這款產品還不太完善,做者自身也提到:在Cacheman作指定key的GET/SET/DELETE操做 時,客戶端須要弄清須要與哪一臺Cacheman服務器通信,爲此要對該key作一個快速FNV哈希而後求餘獲得應該和幾臺服務器中的哪臺服務器通信。但 該法的缺點在於新增或刪除一個服務器節點時,緩存節點須要大規模遷移。修復該問題須要一致性的哈希算法,做者表示尚未時間解決此事。做者提出了採用中心 架構的「主緩存服務器」的解決辦法,讓客戶端輪詢主緩存服務器來獲取應該與那個緩存服務器通信,但他也覺的這樣作增長了複雜性,會帶來些新問題。
能夠感受到,因爲 Cacheman 這個我的項目已經介入到 Popfly 這個正式產品中,可能很快就會被微軟吸納爲正式產品,所以若是有人採用這個產品作本身緩存的解決方案的話,應該沒必要太擔憂後續的產品升級及文檔支持服務, 它的將來前途值的期待。說不定 Krishnan 會從 Popfly 項目脫身出來專職負責這個 Cacheman 項目。