在整個計算機體系構造中(不管是硬件層面仍是軟件層面),緩存都是無處不在的。mysql
在計算機硬件構造中,因爲兩種介質的速度不匹配,高速介質在和低速介質交互時速度趨向低速方,這就致使了高速介質的資源閒置。而經過引入第三種介質(速度和成本介於二者中間),將低速方讀寫的部份內容數據保存在該介質中,高速方大多數狀況下則無需和低速方直接交互,這樣就能總體提高了交互的性能。這就是計算機體系中緩存的由來。比較典型的就是CPU緩存(CPU寄存器=>L1 cahce =>L2 cache =>內存=>硬盤),如圖:算法
在計算機系統和應用軟件層面,緩存更是無處不在。咱們在使用瀏覽器上網時,不少靜態資源會被緩存到本地。咱們在手機上採用微信聊天時,不少好友的頭像等數據會被緩存到手機中。在操做系統層面,I/O操做也會被內核緩存(通常將數據緩存在文件系統的緩存頁中),固然,這個可能相比前兩個場景更加抽象,但緩存的目的都是一致的,爲了提高讀寫性能。sql
緩存在狹義上解決介質讀寫速度不匹配問題,廣義上包括任何利用中間媒介提升速度的方法,包括:空間換時間,動態操做變爲靜態操做。數據庫
緩存(CACHE)和緩衝(BUFFER)編程
緩存:能夠共享,多種數據,大小不固定,能夠重複使用,已知數據,用於提升IO效率。瀏覽器
緩衝:不能夠共享,單一數據,大小固定,讀取後失效,命中100%,未知數據,用於減小IO次數。緩存
緩存的屬性服務器
命中率:從緩存中返回正確數據的次數/總請求次數。微信
容量:超過這個值啓用必定的策略:轉移到磁盤;轉移到遠端;清空部分。session
存儲介質:內存、磁盤。
成本:開發成本、部署成本、硬件成本。
效率:SET效率、GET效率、序列化、哈希算法、分佈式算法。
緩存的限制
因爲價格的因素,緩存實現依賴的存儲每每有大小限制——保存什麼,捨棄什麼,命中率。
緩存每每是從無到有的——在最初階段不能發揮做用,在不命中的時候性能顛簸。
按照存儲介質來分 :
內存(網站進程內、同服務器獨立進程、獨立服務器、分佈式服務器組)。
磁盤(本地文件和數據庫,獨立服務器、分佈式服務器組)。
緩存可使用磁盤而不只僅是內存。
按照存儲的數據來分 :
直接用於輸出的整頁(HTML、腳本樣式、圖片)。
片斷頁(可供多個客戶端使用的HTML、腳本樣式等)。
索引和聚合數據(空間換時間)。
耗時查詢的結果數據。
和業務相關的大塊數據(列表數據,引用數據)。
和業務相關的小級數據(行級數據,資源數據)。
和上下文(用戶)相關的數據(活動數據)。
按照實現方式來分 :
框架或引擎內置的緩存(好比ORM緩存和SQL SERVER緩存)。
安裝特定的組件根據規則自動實現緩存(好比反向代理和輸出緩存)。
須要由開發以編程方式實現的緩存(好比業務數據緩存)。
按照做用來分 :
用於數據的讀取(以後介紹的大部份內容都是基於此類緩存)
用於(容許丟失)數據的寫入——寫到緩存的隊列中,再由工做線程提交處理(寫入存儲)
瀏覽器緩存(HTTP緩存頭)
代理緩存(Squid Vanish CDN)
Web服務器緩存(內核緩存、應用緩存)
頁面輸出緩存(片斷緩存、整頁緩存)
業務數據緩存(本地緩存,分佈式緩存)
其它緩存(ORM、數據庫、搜索引擎等緩存)
這裏每一塊涉及的技術和內容都比較多,暫時不展開。
緩存的常見模式:
緩存的策略:
被動更新
在獲取數據的時候,若是緩存中沒有(可能緩存已通過期了),則嘗試去數據庫中獲取,最後將最新的數據再寫入到緩存中。
主動更新
更新數據的時候,主動更新緩存(直接將數據寫入到緩存中)。
定時更新
經過獨立的線程或者任務調度,定時將緩存數據進行更新。
通知更新
能夠經過MQ等方式來通知緩存更新,這其實也是一種主動更新的策略,必定程度能夠解耦。
不更新
對於有些不可能發生改變的數據,能夠永久緩存起來。
緩存的過時(失效)策略:
絕對的過時時間
這種是最多見的方式。當到達指定時間後,緩存將自動失效。
平滑過時
相似session的超時機制,實際使用較少。
依賴方式
在.NET平臺內置的本地緩存中,支持依賴數據庫或文件來更新緩存,但實際開發中不多用。
永遠不過時
對於有些不可能發生改變的數據,能夠永久緩存起來。
緩存的清除(替換)策略:
RAND 刪除隨機數據,不能反映局部性。
SIZE 刪除最大的數據。
FIFO,First In First Out 刪除最早進入緩存的數據,不能反映局部性。
LFU,Least Frequently Used 刪除一直以來最少被使用的數據。
LRU,Least Recently Used 刪除最近最少使用的數據。
其中,LUR算法是最被普遍使用的。
常見模式:
延遲加載方式:A+F
預加載方式:B/C/E+I
下一篇跟你們聊聊緩存命中率、緩存的常見問題和應對方式...