一、上章回顧
上一章中我們主要簡單的介紹了如何使用服務(wù)器緩存及如何實(shí)現(xiàn)服務(wù)器緩存,下面我們來通過下圖來進(jìn)行詳細(xì)回顧:
1、用戶發(fā)送頁面請求,等待服務(wù)器返回信息。
2、表示層通過請求業(yè)務(wù)層來訪問業(yè)務(wù)數(shù)據(jù)信息。
3、業(yè)務(wù)層在與數(shù)據(jù)訪問層交互時(shí)先與服務(wù)器緩存組件交互。
4、服務(wù)器緩存在接收數(shù)據(jù)請求并處理的過程中判定服務(wù)器緩存中是否存在指定的數(shù)據(jù)集緩存對象。如果存在則返回該緩存對象,否則通過數(shù)據(jù)訪問層,訪問數(shù)據(jù)庫中的數(shù)據(jù),并把數(shù)據(jù)緩存在服務(wù)器組件中。并返回該查詢結(jié)果集。
5、表示層獲得數(shù)據(jù)集合后顯示。
二、摘要
本章將主要講解緩存中的過期策略及如何平衡過期這個(gè)過期策略,怎么樣在項(xiàng)目中解決這樣的問題,這就是本篇要講述的內(nèi)容。
三、本章大綱
1、上章回顧。
2、摘要。
3、本章大綱。
4、具體策略分析。
5、緩存過期策略方案。
6、本章總結(jié)。
7、下篇預(yù)告。
四、具體策略分析
我們我們平時(shí)使用緩存中最頭疼的問題應(yīng)該就是緩存的過期的問題吧,緩存帶來的好處顯而易見,不見提高了網(wǎng)站應(yīng)用程序的性能,同時(shí)提高了訪問的速度,減少了與數(shù)據(jù)庫交互的次數(shù)。無疑是好的方案,所以網(wǎng)上有很多的建議都是,能緩存的數(shù)據(jù)盡量緩存,因?yàn)榫彺姹囟軒硇阅艿奶嵘。同時(shí)有個(gè)很大的問題始終困擾著我們。這樣是我平時(shí)在使用緩存的過程中頭疼的問題。例如這樣的情況:
所以問題就隨之而來,如何保證這個(gè)產(chǎn)品策略的過期性和同步性,當(dāng)然我們知道產(chǎn)品分類一般情況下變化不大,所以我們緩存,對于信息變化或者改變頻率較高的數(shù)據(jù),我們當(dāng)然可以考慮每次加載的時(shí)候都緩存,等到第二次訪問的時(shí)候過期這樣的方式來處理也是可以的?傊鼐褪遣唤(jīng)常改變的常用的數(shù)據(jù)信息能緩存的一定緩存。大家都知道2-8法則的,其實(shí)不管是什么程序基本上都滿足這個(gè)原則。
當(dāng)然Winform的程序則會比較復(fù)雜一些,可能制定的策略相對來說也不好指定。因?yàn)橐话闱闆r下來說客戶端/服務(wù)器這樣的形式,一般的數(shù)據(jù)信息都緩存在客戶端,這樣服務(wù)器壓力小一些,當(dāng)然也有弊端,就是每個(gè)客戶端都是有自己的快照副本,不過由于現(xiàn)在硬件的速度發(fā)展迅速,所以這方面的力度可以考慮加大,顯而易見,當(dāng)數(shù)據(jù)庫中的數(shù)據(jù)發(fā)生改變后,如何通知winform程序進(jìn)行緩存更新也是個(gè)重要的問題,畢竟winform程序的緩存策略與web程序的緩存方式有所不同。當(dāng)然如果說winform也是采用服務(wù)器端緩存的話,當(dāng)然也可以采用上面我們討論的方式來實(shí)現(xiàn)更新策略。
下面我們來看看我理解的可操作的winform的緩存策略的更新。
當(dāng)然上面只是個(gè)人愚見,不足之處還請大家多多指點(diǎn)。歡迎大家拍磚,下面我們來講講各種策略的實(shí)現(xiàn)及優(yōu)缺點(diǎn)。
五、緩存過期策略方案
上面我們簡單的分析了,winform與web應(yīng)用程序的可能的緩存過期策略。下面我們來講講幾種可能的解決方案,當(dāng)然只是個(gè)人愚見,還請大家拍磚,這里只是拋磚引玉,沒有考慮更復(fù)雜的情況。還請大家多多分享自己的經(jīng)驗(yàn)。
1、使用微軟提供的服務(wù)器緩存的過期策略:
a、相對過期。舉個(gè)簡單例子就是,如果緩存對象在某個(gè)時(shí)間段內(nèi)沒有被訪問過,那么該對象則過期,否則則不過期。
b、絕對過期。舉個(gè)簡單例子就是,不管緩存的對象訪問沒有訪問過,只要到達(dá)設(shè)置的時(shí)間則過期。
具體的實(shí)現(xiàn)時(shí),我們可以參考通過配置文件中設(shè)置這個(gè)過期策略,例如我們參考IBatisNet中的緩存
1 <cacheModels>//緩存的對象列表
2 <cacheModel id="CacheLRU_Sys_UserRole" implementation="LRU" >//緩存的對象
3 <flushInterval minutes="2" />//設(shè)置過期策略
4 <flushOnExecute statement="Insert_Sys_UserRole"/>//刷新的動作
5 <flushOnExecute statement="Update_Sys_UserRole"/>
6 <flushOnExecute statement="Delete_Sys_UserRole"/>
7 <property name="CacheSize" value="100"/>//設(shè)置緩存對象的大小
8 </cacheModel>
9 </cacheModels>
顯然通過上面提供的方式可以做到緩存對象的自動過期,但是有個(gè)情況就是不夠靈活,如果緩存對象在指定的時(shí)間段內(nèi)已發(fā)生改變,那么必須在過期時(shí)間后才能更新緩存對象,那么有些時(shí)候顯然不能滿足我的要求,特別是實(shí)時(shí)性的系統(tǒng)時(shí)這樣的緩存策略是不可行的。
2、當(dāng)然上面介紹的IBatisNet中已包含設(shè)置刷新對象時(shí)的操作的設(shè)置:
1 <flushOnExecute statement="Insert_Sys_UserRole"/>//刷新的動作
2 <flushOnExecute statement="Update_Sys_UserRole"/>
3 <flushOnExecute statement="Delete_Sys_UserRole"/>
那么體現(xiàn)在程序中的代碼如何書寫呢,我們來看看。
01 /// <summary>
02 /// 定義委托、用于指向更新緩存的事件
03 /// </summary>
04 /// <returns>返回是否更新緩存</returns>
05 public delegate bool RefreshCache(object sender, EventArgs e);
06
07 /// <summary>
08 /// 維護(hù)緩存更新策略的委托集合
09 /// </summary>
10 public Dictionary<object, List<RefreshCache>> list;
那么通過XML配置相關(guān)的引發(fā)緩存更新的事件來達(dá)到更新緩存的目的。
那么每次委托列表中維護(hù)的對象即是所有的緩存對象的相關(guān)刷新動作事件。通過檢測事件的執(zhí)行來更新緩存對象。
具體的更新緩存的代碼如下:
1 public void RefreshCacheObject(object key,bool isSuccess)
2 {
3 if (!isSuccess)
4 return;
5 if (list.ContainsKey(key))
6 list.Remove(key);
7
8 //載入緩存
9 }
具體的載入緩存的代碼請參考:網(wǎng)站性能優(yōu)化之應(yīng)用程序緩存-初篇
具體的實(shí)現(xiàn)底層通知的代碼我還沒有想好具體的實(shí)現(xiàn)方式(就是比較好的方式)。想好了會把代碼貼上,當(dāng)然IBatisNet已經(jīng)很優(yōu)秀了,我這里也許沒有造輪子的必要,如果誰有比較好的實(shí)現(xiàn)方式,那么可以告訴我,我這里先謝過了,我其實(shí)不是很了解底層的實(shí)現(xiàn)機(jī)制,所以我目前只是采用比較笨的方式來做,雖然也實(shí)現(xiàn)了,但是需要在每個(gè)事件中都要顯示的寫一部分代碼,這是我不能接受的。
3、時(shí)時(shí)更新的方式。
這里的時(shí)時(shí)更新就是指,每次都把數(shù)據(jù)庫中的記錄全部取出來,然后循環(huán)比較結(jié)果集中的記錄與緩存的記錄是不是相同,如果不同則更新該記錄,否則跳過繼續(xù)處理其他的數(shù)據(jù)信息,那么保證緩存中的記錄始終是最新的。當(dāng)然這樣的方式雖然保證所有的緩存信息是最新的,但是每次都與數(shù)據(jù)庫交互顯然不是好的解決方案,當(dāng)然有些情況下也許也是沒有辦法的事情。
最后,本文只是拋磚引玉,希望大家多多提出寶貴意見。
六、本章總結(jié)
本文簡單的介紹了web與winform下的緩存策略,分析了幾種方式的可行性及優(yōu)缺點(diǎn)等,還希望大家在實(shí)際的項(xiàng)目中根據(jù)項(xiàng)目的需要來指定緩存的過期策略,但是可以肯定的是,用緩存肯定比不用緩存的性能要高。當(dāng)然這里也不是要求我們?yōu)E用緩存,也要根據(jù)數(shù)據(jù)信息的更新頻度做一個(gè)平衡,不經(jīng)常變的數(shù)據(jù)一般推薦來緩存。畢竟服務(wù)器中有同一副本,不但能提高訪問的效率,還能減輕數(shù)據(jù)庫的訪問壓力,提高并發(fā)的速度。還需要大家在實(shí)際項(xiàng)目中體會。
七、下篇預(yù)告
本篇并沒有把IBatis.NET中的緩存策略完整的實(shí)現(xiàn),并且也沒有講到其他的一些winform的緩存策略的實(shí)現(xiàn),下一篇將會詳細(xì)的講解這部分的內(nèi)容,當(dāng)然這些都是本人的個(gè)人體會與總結(jié),錯(cuò)誤之處在所難免,歡迎大家提出不同意見,批評指出錯(cuò)誤,謝謝大家!