Q:什麼樣的快取才是好緩存?
能解決問題的快取就是好緩存。這句話簡直就是廢話,相當於白貓、黑貓,抓老鼠的就是好貓。
那在解決問題前提下,哪個快取才是好緩存呢? 這個問題我的答案是:快取命中率高的快取是好緩存。
在解決問題前提下,命中率高的快取比命中率低的緩存,在硬體投入上可能會比較小,同時緩存的數量比命中率低的快取數量也可能少,這樣尋址的速度肯定比較快。所以命中率高的快取是好緩存。
緩存的命中率
一個快取的實體在被丟到快取中後,在這個實體被快取的期間(這個實體被快取的生命週期內),如果外部一次都沒有使用過它,這個快取實體的命中率就是0。這個實體被要求的次數越多,它的快取命中率越高。
上面說的是快取中一個實體的命中率。對於快取整體來說,它的命中率則是上面各個被緩存的個體的命中率分佈圖。
對於快取來說:通常最常使用的個體之佔總體的很小一部分。最不常使用的佔整體的很大一部分。
所以我們常常會看到類似這樣的數據:
在快取的1萬個元素中,有100個被頻繁的使用,幾乎每分鐘都會被使用一次。 2000個數據,每小時被請求一次。 3000個數據,每天被要求一次,剩下的數據,被丟到快取中後一次都沒有被使用過。
現在硬體發展很快,如果我們只是需要緩存1萬個數據的話,我們完全可以做到不管這1萬個數據是否被使用到,全部丟到緩存,這樣只要找數據,肯定緩存中有這個數據。而不需要作額外的運算,或不需要向資料庫發出請求。
但是:硬體發展快,資料量發展也快。小型的網站,快取1萬條數據,也就全部快取了。但是大型網站最少也是上百萬的資料量或是上T等級的數據,這些數據量顯然不能都丟到快取。這時候設計一個合理的快取方案,提高快取的命中率,就非常重要。而且是必須的。
提高快取命中率的一些常見方法
純技術的角度來說,我們只有記錄了使用者的單位時間的請求數,並且依照這個資訊來把最常被使用的資料快取起來。
但更多的時候,我們是根據業務邏輯來提高快取命中率的。例如:去年,前年發表的博客,這類文章的瀏覽請求,一般一天至少可憐的幾次。一般不應該緩存到記憶體中。
又例如,回覆數多的帖子,一般被請求數會比回覆數少的帖子會被更多人次看到。
我們應該透過上面邏輯,根據我們實際業務邏輯,提供一個快取演算法,提高快取的命中率。讓在我們硬體允許的條件下,快取適當的數據,而不是所有數據。
一個反面的例子就是:不管三七二十一,一個大型的博客站點,一篇文章被用戶請求的時候,發現不在內存緩存中,就從數據庫中讀出,然後丟到緩存。
要知道,現在爬蟲程序很多的。另外,部落格這類搜尋引擎友善的站點,決大多數的訪問壓力是搜尋引擎搜尋過來的。而這些訪問一般都是1小時,或者1 天之內,對某篇文章只有幾次甚至1次請求,之後再也沒有了。上面作快取的方法,命中率會非常低的。
這裡也許就有人會問,郭紅俊,既然你不建議我緩存這些博客的內容,但是我如何提高我站點的性能呀,我至少得保證我博客站點不會速度慢的無法響應用戶請求呀。
這個問題的解決方案有很多,一個最簡單的方法就是把這些部落格做成靜態Html頁面,也就是檔案系統的緩存,檔案系統因為硬碟的原因,可以簡單理解成可以無限擴容,這樣就可以把很多命中率低的內容進行快取。
如果你的頁面需要一些動態邏輯判斷,你可以把資料快取成XML文件,然後伺服器區段整合這些XML文件,或是包含文件。這也是種不錯的方法。
說了這麼多快取命中率的問題,簡單總結一下快取命中率的觀點:
小型網站可以全部資料緩存,一般壓力也不會很大,可以忽略緩存命中率問題。
大型服務無法全部資料緩存,只能部分資料緩存,這時候就需要架構師設計出對該業務邏輯適用的快取方法,盡可能提高快取的命中率。
提高命中率的方法大多是跟業務邏輯捆綁的,需要跟具體問題具體分析對於不能被內存緩存的數據,最簡單的提高性能方法就是使用文件緩存。
文件快取可以整個內容緩存成一個靜態文件;也可以是整個頁面的一個區域被緩存成一個文件,然後被包含;也可以是把一個實體序列化成XML 文件進行緩存。
下面我們來看看快取的其他幾個不那麼重要的方面:
緩存的生命週期內的活動
永久不過期,永久不變更的內容,這類東西就不該放在快取。快取是臨時的存儲,而不是永久的,所以快取的生命週期是有限的。
它依次可能會經歷如下活動:
進入緩存。 (進入快取的時候,可能需要指定它以後的過期策略,如果不指定,需要使用系統預設的過期策略)
從快取中獲得它,注意,這時候需要處理線程安全的問題。
更新緩存,注意,也需要考慮線程安全問題離開緩存,這個可能是外部請求,也可能是緩存根據過期策略把它清理掉。
快取的過期策略
一般我會問,你所接觸的快取中,碰到過那些快取過期策略?
最常見的幾種過期策略如下:
多長時間沒有被要求,則過期,最典型的就是ASP和ASP.net 提供的Section 功能。其實它就是一個快取。
依賴檔案變更的緩存,一旦檔案被修改,快取則過期,典型的是WEB站點的Web.config ,一旦這個檔案變更,不但快取重起,IIS進程也會進行一次釋放工作。
在此基礎上,可能會看到許多依賴關係的快取過期策略。例如依賴資料庫的快取過期策略。
當然,業務邏輯裡可能會有更複雜的過期策略,必須CSDN新版積分制論壇中,貼文清單快取會在清單資料快取達到600時,把它清理到550條資料。
又例如新積分制論壇貼文的快取過期,則是沒有任何清單引用這個貼文後,則這個貼文過期。
快取的同步問題
使用緩存,則意味著同樣的數據,可能有多份並存。如果你的程式碼沒有考慮某種情況,導致了這兩份資料不一致了。這時候就會有問題發生。
解決方法很簡單,把你的業務邏輯,程式碼觸發狀況都考慮清楚,不要遺留沒有觸底的地方。
簡單的方法會導致你的程式碼邏輯變得非常複雜。
這也就是有些人,在非必要的時候,建議你不要用快取的原因。一旦開始使用緩存,你就應該準備增加大量的程式碼來處理資料同步的問題。
初始化填充快取數據
有時候在快取被初始化後,還需要預先填充一些資料到快取中。這就是快取資料的初始化操作。
快取資料的初始化操作需要考慮以下問題:
需要多長時間進行初始化,一般如果是網站的話,我們可能在Global.asa 的Application_OnStart 中處理這個初始化工作。初始化的一般不能太久,這時候就是考驗我們程式碼優化的能力了。
初始化的時候,一般是批量導入數據,而不是我們正常使用的時候,一次處理一個數據。
總結:
本文介紹了我對快取的一些觀點,而沒有深入涉及到具體的快取技術。希望透過本文的敘述,讓只會快取用法不懂快取思想的人有初步的了解。
http://blog.csdn.net/ghj1976/archive/2007/09/01/1768676.aspx