走進緩存的世界(一) - 開篇


系列文章

 

概述

對於程序員來說多多少少都懂一點算法,算法是什么?算法是“時間”與“空間”的互換策略。

我們常常研究一個算法的時間復雜度和空間復雜度,如果我們有絕對足夠的時間和空間,那么算法就不需要了,可惜這種條件是不存在的,只是在某些情況下我們會協調兩者從而達到性能上的平衡。

緩存是一種“用空間換時間”的策略,通俗的講,緩存就是把一些數據暫時存儲起來,避免了某些重復的耗時操作,減少時間開銷的一種方法。

商業世界中常說的一句話是“現金為王”。在技術世界里,與之相近的一個說法是“緩存為王”。

從底層到上層主要涉及:數據庫模型設計,SQL優化,使用緩存等。從圖中的優化模式來看,其中數據庫模型設計的合理程度奠定了應用系統優化的基石,如果模型設計得不合理,隨着業務發展,后續的優化將會變得很困難。另一方SQL優化也是數據庫優化的一個重要方面,慢SQL和top SQL往往是系統性能殺手,它們是導致系統故障的重要潛在危險。

緩存在構建高性能服務器中有着舉足輕重的作用,很多時候sql優化, 算法優化所帶來的效果可能遠遠不如緩存帶來的優化效果。但是緩存的使用並不是零成本的,任何緩存的增加,都會帶來兩大問題:

  • 數據不一致
  • 系統復雜度大幅度增加

如何解決呢?首先考慮去掉緩存。不要為了緩存而緩存,緩存不必要時,應該果斷去掉,從而降低系統出錯的可能性和系統復雜度。有些對數據實時性,准確性要求極高的系統,不能使用緩存。其次是分析需求,不同的業務會有不同的緩存策略,仔細分析變化與不變的數據,將不變的數據長時間緩存,變化的數據根據數據的業務要求動態調整緩存時間和存儲方式。最后就是增加開發人員自身的能力,后面會詳細提及各種問題的處理方法。

什么樣的緩存才是好緩存

什么樣的員工是好員工?最直接最本質的回答:能辦事、且辦事靠譜就是好員工,答案並不是聰明、勤奮、社交好等等,這些只是成為一個靠譜員工的充要條件。

什么樣的緩存才是好緩存呢?答案是:命中率高的緩存。

在解決問題前提下,命中率高的緩存比命中率低的緩存,在硬件投入上一般會小很多,緩存數量比命中率低的緩存數量也少很多,尋址速度肯定也比較快,所以命中率高的緩存是好緩存。

緩存的設計需要考慮緩存的占用空間和命中率。我們當然希望緩存占用空間小,命中率高。命中率高是緩存設計的重要考察因素, 是提高系統性能的關鍵。占用空間越小,需要的成本越低。低成本,高效能的緩存設計是我們追求的目標。這沒有固定的設計方法和公式,需要根據不同的業務靈活調整,但是,關於緩存在業務開發中的設計方法,有一些比較常用的思路與模式,借鑒這些模式,我們可以復用或創新,解決新的業務中所出現的問題。

緩存的命中率

一個實體丟到緩存中后,在被緩存期間,如果一次都沒有使用過,這個緩存實體的命中率就是0。這個實體被請求的次數越多,緩存命中率越高。

上面說的是緩存中一個實體的命中率。對於緩存整體來說,命中率=命中數/總查找數。

對於緩存來說:通常最常使用的個體占總體的很小一部分,最不常使用的占整體的很大一部分.。

所以我們經常會看到類似這樣的數據:

緩存的1萬個元素中,有100個被頻繁的使用,幾乎每分鍾都會被使用一次。2000個數據,每小時被請求一次。3000個數據,每天被請求一次,剩下的數據,被丟到緩存中后一次都沒有被使用過。

現在硬件發展很快,如果我們只是需要緩存1萬個數據的話,我們完全可以做到不管這1萬個數據是否被使用到,全部丟到緩存,這樣只要找數據,肯定緩存中有這個數據。而不需要作額外的運算,或者不需要向數據庫發出請求。

但是:硬件發展快,數據量發展也快。小型的網站,緩存1萬條數據,也就全部緩存了。但是大型網站最少也是上百萬的數據量或者上T級別的數據,這些數據量顯然不能都丟到緩存。這時候設計一個合理的緩存方案,提高緩存的命中率,就非常重要而且是必須的。

如何提高緩存命中率

純技術的角度來說,我們只有記錄了用戶單位時間的請求數,並依照它來把最常使用的數據緩存起來,從而提高緩存命中率。

但更多的時候,我們是根據業務邏輯來提高緩存命中率的。比如:去年,前年發表的博客,這類文章的瀏覽請求,一般一天也就幾次訪問,不應該緩存到內存中。

我們應該通過上面邏輯,根據我們實際業務邏輯,提供一個緩存算法,提高緩存的命中率。讓在我們硬件允許的條件下,緩存適當的數據,而不是所有數據。

一個反面的例子就是:不管三七二十一,一個大型的博客站點,一篇文章被用戶請求的時候,發現不在內存緩存中,就從數據庫中讀出,然后丟到緩存。

要知道,現在爬蟲程序很多的。另外,博客這類搜索引擎友好的站點,絕大多數訪問壓力是搜索引擎導入的。而這些訪問一般都是1小時,或者1天之內,對某篇文章只有幾次甚至1次請求,之后再也沒有了,這種緩存方法,命中率會非常低。

說了這么多緩存命中率的問題,簡單匯總一下緩存命中率的觀點:

  • 小型網站可以全部緩存,壓力也不會很大,可以忽略緩存命中率問題
  • 大型服務無法全部緩存,時候就需要架構師設計出對該業務邏輯適用的緩存方法,盡可能提高緩存命中率
  • 提高命中率的方法大多是跟業務邏輯捆綁的,需要跟具體問題具體分析
  • 對於不能被內存緩存的數據,最簡單的提高性能方法就是使用文件緩存
  • 文件緩存可以整個內容緩存成一個靜態文件,也可以是整個頁面的一個區域被緩存成一個文件,也可以是把一個實體序列化成XML文件進行緩存

過期策略

緩存是臨時的存儲,所以緩存的生命周期是有限的。它依次可能會經歷如下活動:

  • 進入緩存
  • 正常使用期
  • 更新緩存
  • 離開緩存

最常見的幾種過期策略如下:

多長時間沒有被請求,則過期,最典型的就是ASP的Section 功能。

依賴於文件變更的緩存,一旦文件被修改,則過期,典型的是WEB站點的Web.config,一旦這個文件變更,不但緩存重起,IIS進程也會進行一次釋放工作。

在此基礎上,引申出很多依賴關系的緩存過期策略,比如依賴於數據庫的緩存過期策略。

當然,業務邏輯里可能會有更復雜的過期策略,比如CSDN新版積分制論壇中,帖子列表緩存會在列表數據緩存達到600時,把它清理到550條數據。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM