性能優化--緩存篇


緩存的應用場景

CPU緩存

是位於CPU與內存之間的臨時存儲器,它的容量比內存小的多但是交換速度卻比內存要快得多。(選用存儲介質,提高訪問速度:高速緩存>內存;減少重復量)

瀏覽器緩存

瀏覽器可以緩存一些靜態資源,比如圖片、js、css等,這些都是不常變化的內容,所以沒有必要每次都去請求。(減少網絡IO消耗,提高訪問速度)

這里寫圖片描述

CDN緩存

客戶端會先檢查瀏覽器的緩存,若緩存過期則會像CDN發送請求(Request),CDN檢查緩存數據還未過期,那么直接返回響應(Response),只需兩步搞定。但是,CDN緩存過期,那么需要向應用服務器(Web Server)發起請求,獲得新的數據響應,這部分新的數據按一定的緩存策略會選擇是否緩存在CDN中。從下圖可發現,此時數據需要完成1–>3–>4–>2最終返回到瀏覽器端。此處的CDN,(減少網絡IO消耗,提高訪問速度)

這里寫圖片描述

數據庫緩存

我們看下圖,在WebServer和DB之間加一層cache,這層cache一般選取的介質是內存,因為我們都知道存入數據庫的數據都具有持久化的特點,那么讀寫會有磁盤IO的操作,內存的讀寫速度遠比磁盤快得多。(選用存儲介質,提高訪問速度:內存>>磁盤;減少磁盤IO的操作,減少重復查詢,提高吞吐量)

這里寫圖片描述

業務層緩存

除了上面介紹的緩存場景,我們還可能需要更細粒度的緩存,可以在上圖的某個切面做更細致處理,下篇我們將從實踐方面來探討業務上的緩存。


存儲介質訪問速度比較 來自Google工程師Jeff Dean的分享,僅供參考:

存儲介質 速度
L1 cache reference 讀取CPU的一級緩存 0.5 ns
Branch mispredict(轉移、分支預測) 5 ns
L2 cache reference 讀取CPU的二級緩存 7 ns
Mutex lock/unlock 互斥鎖\解鎖 100 ns
Main memory reference 讀取內存數據 100 ns
Compress 1K bytes with Zippy 1k字節壓縮 10,000 ns
Send 2K bytes over 1 Gbps network 在1Gbps的網絡上發送2k字節 20,000 ns
Read 1 MB sequentially from memory 從內存順序讀取1MB 250,000 ns
Round trip within same datacenter 從一個數據中心往返一次,ping一下 500,000 ns
Disk seek 磁盤搜索 10,000,000 ns
Read 1 MB sequentially from network從網絡上順序讀取1兆的數據 10,000,000 ns
Read 1 MB sequentially from disk 從磁盤里面讀出1MB 30,000,000 ns
Send packet CA->Netherlands->CA 一個包的一次遠程訪問 150,000,000 ns

緩存的工作原理

一句話概況:更快讀寫的存儲介質+減少IO+減少CPU計算=性能優化。

通過上述應用場景(標紅部分),我們可知緩存的基本原理就是通過這幾個方面來進行優化的。

在實際應用中,我們需要對數據進行分類,才能更好的使用緩存以及一些策略來輔助。比如哪些為冷熱數據?哪些數據量很大,讀取會嚴重影響IO?哪些數據查多改少(日志數據,爬蟲數據)?哪些數據又是經過很復雜的計算得到的結果(這些珍貴的數據需要好好保存利用)?……


緩存帶來的好處

顯而易見,緩存給我們帶來最直接的體驗就是“快”,我們來總結一下:

  1. 通過減少IO(包括磁盤和網絡)來提高吞吐量,減少計算量(CPU計算)釋放CPU,這些都是提高系統的響應速度。

  2. 通過切面的處理方式,可以在各層進行插拔,是所有性能優化最簡單有效的解決方案。(對於不熟悉業務代碼或算法的優化者,顯然加一層緩存的復雜度和風險更低,而這一層看似簡單的緩存,它給系統帶來的性能優化有可能大大超過前者)


緩存帶來的困擾

我們不能否認緩存給我們帶來諸多便利,同時,我們不能忽略緩存確實也給我們帶來了不少困擾:

  1. 數據的一致性、實時性受影響。(需要對數據的一致性,時效性進行評估,進而確定是否要緩存或設定緩存的過期時間,比如個性化的數據是否值得緩存?)

  2. 緩存介質帶來的不可靠性。(一般使用內存做緩存的話,若機器故障,如何保證緩存的高可用?可考慮對緩存進行分布式做成高可用,同時,需要接受這種不可靠不安全會給數據帶來的問題,在異常情況下進行補償處理,定期持久化等方式)

  3. 緩存的數據使得更難排查問題。因為緩存命中是隨着訪問隨時變化的,緩存的行為難以重現,使得出現BUG很難排查。

  4. 進程內緩存可能會增加GC壓力:在具有垃圾收集功能的語言中(如java),大量長壽命的緩存對象會增加垃圾收集的時間和次數。

我前面提到的,使用緩存之前我們需要對數據進行分類,對訪問行為進行預估,思考哪些數據需要緩存,緩存時需要采用什么策略?這樣,我們才不被緩存所困擾,才能規避這些問題。


常用的緩存工具

業務上緩存,常用 and 開源的緩存工具有:ehcache、memcache、redis。

  1. ehcache 是一個純Java的進程內緩存框架,hibernate使用其做二級緩存。同時,ehcache可以通過多播的方式實現集群。本人主要用於本地的緩存,數據庫上層的緩存。

  2. memcache是一套分布式的高速緩存系統,提供key-value這樣簡單的數據儲存,可充分利用CPU多核,無持久化功能。本人在做web集群的時候用過,主要做session共享,頁面對象緩存。

  3. redis高性能的key-value系統,提供豐富的數據類型,單核CPU有抗並發能力,有持久化和主從復制的功能。本人主要使用redis的redis sentinel,根據不同業務分為多組。


免責聲明!

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



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