1. 程式人生 > >java中的快取

java中的快取

@Service就相當於new了這個Service類,可供Controller呼叫


ehcache的快取有兩種方式,一種是用Ehcache Annotations for Spring在業務邏輯層裡對其進行快取
,另一種是在mybatis裡面用mybatis-ehcache對其進行快取,這兩種有必要共存嗎,如果不必要,
應該使用哪一種比較合理,或者是說常用的是哪一種???


快取是在資料庫查詢的時候進行快取
第二次呼叫資料庫查詢就可以去快取查


查詢語句有 setCache


想用ehcache進行快取管理,如果在業務邏輯層
加上了快取,那麼在mybatis還需要再加上ehcache的快取嗎?



<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.2.5</version>






web中快取的幾種方式


看了構建高效能的web站點一書,對其中的集中web快取進行一個總結


1 應用程式實現的動態頁面快取


應用程式把動態檔案生成的html檔案快取到檔案伺服器,以後使用者請求動態檔案,直接從檔案伺服器載入對應的靜態快取的html檔案返回給使用者,這裡面主要節省了動態語言的執行時間和資料庫訪問時間。但是會增加了快取框架的載入和快取查詢的時間。


 


2 把解釋執行的開發語言編譯成為目的碼


這個主要把解釋執行的高階語言,例如java,php直接編譯成為平臺相關的目的碼,彙編程式碼。在java裡面,比較著名的就是即時編譯器(JIT),其他的語言也要類似的機制。這裡面主要節省了就是解釋執行程式碼的時間。這個會增加即時編譯的時間。


 


3 利用反向代理伺服器的快取


利用類似nginx的反向代理伺服器,對請求的url對應的輸出的進行快取。這個快取和應用程式實現的動態頁面快取類似,只不過用反向代理充當了應用程式的快取實現。主要節省了動態餘元執行時間和資料庫訪問時間。


 


4 客戶端瀏覽器快取


客戶端瀏覽器快取主要是通過在http頭部增加


Last-Modified,If-Modified-Since,Expires,Cache-Control等標識,和伺服器進行協商,是否是採用客戶的本機快取來實現。


其中這裡面也會分為三種方式


1 通過Last-Modified,If-Modified-Since方式和伺服器通訊,客戶發出http請求中包含If-Modified-Since,如果伺服器端程式碼沒有修改,伺服器端返回302響應程式碼的請求響應頭(內容不返回)客戶端則直接用本機快取的內容快取顯示結果。相當於節省了伺服器執行程式碼時間以及資料傳輸時間。


2 通過Expires,Cache-Control控制,客戶端發現如果上次請求的頁面還未過期,通過Expires或者Cache-Control進行辨別,則直接顯示本機快取的內容,不與伺服器進行通訊。


 


總結一下:1 一般的高併發的應用程式,都在web層採用了以上幾種快取,一般靜態資源(圖片,js,css)都會採用nginx反向代理+客戶端快取來實現。


              2  對於入口網站,尤其是首頁的新聞,一般都會快取起來,可以通過反向代理也可以通過應用程式快取實現方式


              3 對於下載或者視訊網站,由於資料傳輸比較大,直接採用瀏覽器本地快取實現。


 
 
 


快取機制詳解
一. 為什麼要使用快取
如果每次進入頁面的時候都查詢資料庫生成頁面內容的話,如果訪問量非常大,則網站效能會非常差。而如果只有第一次訪問的時候才查詢資料庫生成頁面內容,以後都直接輸出內容,則能提高系統性能。這樣無論有多少人訪問都只訪問一次資料庫,資料庫壓力不變。
二. 什麼是快取:
快取(Cache)是一種用空間換取時間的技術,存在於計算機中很多地方,用來將一些慢速裝置中的常用資料儲存在快速裝置中,取資料的時候直接從快速裝置中取。比如CPU二級快取、記憶體、windows檔案讀取快取。快取是改進網站效能的第一個手段,就像索引是改進資料庫效能的第一個手段一樣
 
三. 快取存在的問題:
   快取存在失效的問題:為了保證從快取中讀取資料和慢速資料(資料庫)中資料一致,則需要在慢速資料(資料庫)中對應的資料發生變化的時候,清除快取中相應的資料(快取依賴)。
四. 下面介紹asp.net中的三種形式的快取:
  頁面快取(中庸)、資料來源快取(最不靈活的)、資料快取(靈活)這三種主要型別。
 
1) 頁面快取:
簡單的有關介紹:
l 給頁面新增<%@ OutputCache Duration=“15”  VaryByParam=“none”%>標籤就可以啟用頁面快取,這樣整個頁面的內容都會被快取,頁面中的ASP.Net程式碼、資料來源在快取期間都不會被執行,而是直接輸出快取的頁面內容。 Duration表示快取時間,以秒為單位,超過這個時間則快取失效,再次生成以後會再快取15秒,以此類推。在Page_Load處設定斷點、修改資料庫資料測試。這個快取是在伺服器快取的,不是在客戶端,因為用HttpWatch還是能看到向伺服器提交的請求的,只不過伺服器看到有快取就沒有再執行頁面類。一般只有看帖、看新聞、看視訊的頁面才快取,CUD的頁面沒必要快取。
l 快取是針對所有這個頁面的訪問者。這樣1個訪問者和1萬個訪問者、一次訪問和100萬次訪問對資料庫的壓力是一樣的。
l 下面開始介紹也頁面快取機制:
當瀏覽器第一次請求頁面後,傳送了請求報文,伺服器端會分析請求的報文,然後判端伺服器快取中有沒有該頁面的資料的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進行判斷快取是否消失。
 
   但是問題又來了:
 
l 對於看新聞頁面來講,如果如上設定的話,則會快取在第一個看到的新聞,因為?id=2、?id=3只是頁面的不同引數而已,為了能讓不同的新聞各自快取,因此可以設定VaryByParam=“id”,表示對於相同頁面的不同的id引數進行單獨快取。如果有多個確定快取的引數,則將引數名用分號隔開即可,比如VaryByParam=“id;number”。測試。快取可能會有過期資料的問題,因此根據需求選用。
l 如果想讓任何不同的查詢字串都建立不同的快取,則設定VaryByParam="*",一般情況下設定“*”就足夠。
l 所以設定VaryByParam=”none“是不管你帶上什麼引數,在伺服器端快取的都是第一次訪問的頁面。 如果參上多個引數,就會根據你的引數來快取不同的頁面的資料的html程式碼。
 
2) 資料來源快取:
設定ObjectDataSource的CacheDuration(快取時間:秒),EnableCaching=true。這樣每隔CacheDuration指定的時間段才呼叫SelectMethod指定的方法來執行資料庫查詢,其他時候都是直接返回快取的資料。取資料的過程快取,在快取期間,繫結控制元件向ObjectDataSource要資料, ObjectDataSource直接將快取的資料返回給控制元件,不再去向TypeName指向的類要資料。
 
注意:
快取固定的時間適用於首頁、文章列表等訪問頻繁的頁面,對於看貼頁面則不適合,假設有100萬個帖子,如果每個帖子都是固定快取1小時的話,假設一小時之內有10萬個帖子被看了,那麼就要快取十萬個帖子,非常佔用記憶體,因為“百年一看”的“墳帖”偶然被訪問一次也快取一個小時,佔用記憶體。這時候可以採用“滑動視窗(sliding)”策略,比如帖子快取10分鐘,如果10分鐘之內又訪問了,則快取的失效時間修改為從被訪問這一刻起的10分鐘之後,以此類推。這樣經常訪問的帖子就可以“長期快取”,而不經常訪問的帖子也不會因為偶然訪問而長期佔用快取。設定方法,資料來源:CacheExpirationPolicy="Sliding"。面試可聊。todo:貌似滑動有問題。不是問題,Sliding只是策略,伺服器會參考。
 
3)快取依賴:
l  依賴於檔案內容
CacheDependency cDep = new CacheDependency(filePath);
l 依賴於資料庫內容(輪詢機制/通知機制)
一:輪詢機制 –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是要快取的物件的資料。