緩存技術

開始討論緩存以前,讓咱們先來討論討論另一個問題:理論和實踐.從ahuaxuan接觸的程序員來看,有的程序員偏實踐,有的程序員偏理論,可是這都是很差的行爲,理論和實踐一樣重要,咱們在作不少核心的算法的時候,沒有理論根本無從下手,而在咱們多年的實踐中,不總結理論就不能加深本身的理解.因此理論和實踐同等重要. 

緩存是當今各類軟件或者硬件系統中不可缺乏的技術之一,因此對每一個程序員來講都顯得異常重要,對ahuaxuan來講亦是如此.若是說用dfa實現文字過濾是從理論到實踐,那麼本文即是從實踐中總結出得理論. 

在討論緩存功能以前,咱們首先來了解一下緩存這個東西自己.ahuaxuan根據本身的經驗把緩存問題細分爲4類小問題. 

1緩存爲何要存在? 
2緩存能夠存在於什麼地方? 
3緩存有哪些屬性? 
4緩存介質? 

搞清楚這4個問題,那麼咱們就能夠隨意的經過應用的場景來判斷使用何種緩存了. 

下面ahuaxuan和你們一一分析這4個問題. 
1. 緩存爲何要存在? 
通常狀況下,一個網站,或者一個應用,它的通常形式是,瀏覽器請求應用服務器,應用服務器作一堆計算後再請求數據庫,數據庫收到請求後再做一堆計算後把數據返回給應用服務器,應用服務器再做一堆計算後把數據返回給瀏覽器.這個是一個標準流程.可是隨着互連網的普及,上網的人愈來愈多,網上的信息量也愈來愈多,在這兩個愈來愈多的狀況下,咱們的應用須要支撐的併發量就愈來愈多.而後咱們的應用服務器和數據庫服務器所作的計算也愈來愈多,可是每每咱們的應用服務器資源是有限的,數據庫每秒中接受請求的次數也是有限的(誰叫俺們的硬盤轉速有限呢).若是利用有限的資源來提供儘量大的吞吐量呢,一個辦法:減小計算量,縮短請求流程(減小網絡io或者硬盤io),這時候緩存就能夠大展手腳了.緩存的基本原理就是打破上圖中所描繪的標準流程,在這個標準流程中,任何一個環節均可以被切斷.請求能夠從緩存裏取到數據直接返回.這樣不但節省了時間,提升了響應速度,並且也節省了硬件資源.可讓咱們有限的硬件資源來服務更多的用戶. 

2 緩存能夠存在於什麼地方? 
Java代碼java

  1. 瀏覽器---瀏覽器和app之間---分過層的app-數據庫  node

        瀏覽器---瀏覽器和app之間---分過層的app-數據庫

在上圖中,咱們能夠看到一次請求的通常流程,下面咱們從新繪製這張圖,讓咱們的結構稍微複雜一點點. 
(將app分層) 
        瀏覽器---瀏覽器和app之間---分過層的app-數據庫 


理論上來將,請求的任何一個環節都是緩存能夠做用的地方.第一個環節,瀏覽器,若是數據存在瀏覽器上,那麼對用戶來講速度是最快的,由於這個時候根本無需網絡請求.第二個環節,瀏覽器和app之間,若是緩存加在這個地方,那麼緩存對app來講是透明的.並且這個緩存中存放的是完整的頁面.第三個節點,app中自己就有幾個層次,那麼緩存也能夠放在不一樣的層次上,這一部分是狀況或者場景比較複雜的部分.選擇緩存時須要謹慎.第四個環節,數據庫中也能夠有緩存,好比說mysql的querycache. 

那麼也就是說在整個請求流程的任何一點,咱們均可以加緩存.可是是全部的數據均可以放進緩存的嗎.固然不是,須要放進緩存的數據老是有一些特徵的,要清楚的判斷數據是否能夠被緩存,能夠被怎樣緩存就必需要從數據的變化特徵下手. 

數據有哪些變化特徵?最簡單的就是兩種,變和不變.咱們都知道,不會變化的數據不須要每次都進行計算.問題是難道全部的數據理論上來說都會變化,變化是世界永恆的主題.也就是說咱們把數據分爲變和不變兩種是不對的,那麼就讓咱們再加一個條件:時間.那麼咱們就能夠把數據特徵總結爲一段時間內變或者不變.那麼根據這個數據特徵,咱們就能夠在合適的位置和合適的緩存類型中緩存該數據. 

3緩存有哪些屬性 
從面向對象的角度來看,緩存就是一個對象,那麼是對象,必然有屬性.那麼下面咱們來探討一下緩存有哪些屬性.如下列舉咱們經常使用到的3個屬性. 
(1) 命中率 
命中率是指請求緩存次數和緩存返回正確結果次數的比例.比例越高,就證實緩存的使用率越高. 

命中率問題是緩存中的一個很是重要的問題,咱們都但願本身緩存的命中率能達到100%,可是每每事與願違,並且緩存命中率是衡量緩存有效性的重要指標. 

(2) 最大元素 
緩存中能夠存放得最大元素得數量,一旦緩存中元素數量超過這個值,那麼將會起用緩存清空策略,根據不一樣的場景合理的設置最大元素值每每能夠必定程度上提升緩存的命中率.從而更有效的時候緩存.

(3) 清空策略 

1 FIFO ,first in first out ,最早進入緩存得數據在緩存空間不夠狀況下(超出最大元素限制時)會被首先清理出去 
2 LFU , Less Frequently Used ,一直以來最少被使用的元素會被被清理掉。這就要求緩存的元素有一個hit 屬性,在緩存空間不夠得狀況下,hit 值最小的將會被清出緩存。 
2 LRU ,Least Recently Used ,最近最少使用的,緩存的元素有一個時間戳,當緩存容量滿了,而又須要騰出地方來緩存新的元素的時候,那麼現有緩存元素中時間戳離當前時間最遠的元素將被清出緩存。 

4緩存介質 
從硬件介質上來將無非就是兩種,內存和硬盤(對應應用層的程序來說不用考慮寄存器等問題).可是每每咱們不會從硬件上來劃分,通常的劃分方法是從技術上劃分,能夠分紅幾種,內存,硬盤文件.數據庫. 
(1) 內存.將緩存放在內存中是最快的選擇,任何程序直接操做內存都比操做硬盤要快的多,可是若是你的數據要考慮到break down的問題,由於放在內存中的數據咱們稱之爲沒有持久話的數據,若是硬盤上沒有備份,機器down機以後,很難或者沒法恢復. 

(2) 硬盤.通常來講,不少緩存框架會結合使用內存和硬盤,好比給內存分配的空間有滿了以後,會讓用戶選擇把須要退出內存空間的數據持久化到硬盤.固然也選擇直接把數據放一份到硬盤(內存中一份,硬盤中一份,down機也不怕).也有其餘的緩存是直接把數據放到硬盤上. 


(3) 數據庫.說到數據庫,可能有的人會想,以前不是講到要減小數據庫查詢的次數,減小數據庫計算的壓力嗎,如今怎麼又用數據庫做爲緩存的介質了呢.這是由於數據庫又不少種類型,好比berkleydb,這種db不支持sql語句,沒有sql引擎,只是key和value的存儲結構,因此速度很是的快,在當代通常的pc上,每秒中十幾w次查詢都是沒有問題的(固然這個是根據業務特徵來決定的,若是您訪問的數據在分佈上是均勻的,那ahuaxuan可不能保證這個速度了). 

除了緩存介質以外,ahuaxuan根據緩存和應用的耦合程度將其劃分爲local cache和remote cache. 
Local cache是指包含在應用之中的緩存組件.而remote cache指和應用解耦在應用以外的緩存組件.典型的local cache有ehcache,oscache,而remote cache有大名鼎鼎的memcached. 

Localcache最大的優勢是應用和cache的時候是在同一個進程內部,請求緩存很是快速,徹底不須要網絡開銷等.因此單應用,不須要集羣或者集羣狀況下cache node不須要相互通知的狀況下使用local cache比較合適.這也是java中ehcache和oscache這麼流行的緣由. 
可是Local cache是有必定的缺點的,通常這種緩存框架(好比java中的ehcache或者oscache)都是local cache.也就是跟着應用程序走的,多個應用程序沒法直接共享緩存,應用集羣的狀況下這個問題更加明顯,固然也有的緩存組件提供了集羣節點相互通知緩存更新的功能,可是因爲這個是廣播,或者是環路更新,在緩存更新頻繁的狀況下會致使網絡io開銷很是大,嚴重的時候會影響應用的正常運行.並且若是緩存中數據量較大得狀況下使用localcache意味着每一個應用都有一份這麼大得緩存,着絕對是對內存的浪費. 

因此這個狀況下,每每咱們會選擇remote cache,好比memcached.這樣集羣或者分佈式的狀況下各個應用均可以共享memcached中的數據,這些應用都經過socket和基於tcp/ip協議上層的memcached協議直接鏈接到memcached,有一個app更新了memcached中的值,全部的應用都能拿到最新的值.雖然這個時候多了不少了網絡上的開銷,可是每每這種方案要比localcache廣播或環路更新cache節點要廣泛的多,並且性能也比後者高.因爲數據只須要保存一份,因此也提升了內存的使用率. 

經過以上分析能夠看出,無論是local cache,仍是remote cache在緩存領域都有本身的一席之地,因此ahuaxuan建議在選擇或者使用緩存時必定要根據緩存的特徵和咱們的業務場景準確判斷使用何種緩存.這樣才能充分發揮緩存的功能. 

Ahuaxuan認爲,緩存的使用是架構師的必備技能,好的架構師可以根據數據的類型,業務的場景來準確的判斷出使用何種類型的緩存,而且如何使用這種類型的緩存.在緩存的世界裏也沒有銀彈,目前尚未一種緩存能夠解決任何的業務場景或者數據類型,若是這種技術出現了,那架構師就又更不值錢了.呵呵.mysql

 

OSCache
  
  OSCache是個一個普遍採用的高性能的J2EE緩存框架,OSCache能用於任何Java應用程序的普通的緩存解決方案。
  
  OSCache有如下特色:
  
  緩存任何對象,你能夠不受限制的緩存部分jsp頁面或HTTP請求,任何java對象均可以緩存。
  
  擁有全面的API--OSCache API給你全面的程序來控制全部的OSCache特性。
  
  永久緩存--緩存能隨意的寫入硬盤,所以容許昂貴的建立(expensive-to-create)數據來保持緩存,甚至能讓應用重啓。
  
  支持集羣--集羣緩存數據能被單個的進行參數配置,不須要修改代碼。
  
  緩存記錄的過時--你能夠有最大限度的控制緩存對象的過時,包括可插入式的刷新策略(若是默認性能不須要時)。
  
  官方網站 http://www.opensymphony.com/oscache/
  
  Java Caching System 
  
  JSC(Java Caching System)是一個用分佈式的緩存系統,是基於服務器的java應用程序。它是經過提供管理各類動態緩存數據來加速動態web應用。
  
  JCS和其餘緩存系統同樣,也是一個用於高速讀取,低速寫入的應用程序。
  
  動態內容和報表系統可以得到更好的性能。
  
  若是一個網站,有重複的網站結構,使用間歇性更新方式的數據庫(而不是接二連三的更新數據庫),被重複搜索出相同結果的,就可以經過執行緩存方式改進其性能和伸縮性。
  
  官方網站 http://jakarta.apache.org/turbine/jcs/
  
  EHCache 
  
  EHCache 是一個純java的在進程中的緩存,它具備如下特性:快速,簡單,爲Hibernate2.1充當可插入的緩存,最小的依賴性,全面的文檔和測試。
  
  官方網站 http://ehcache.sourceforge.net/
  
  JCache 
  
  JCache是個開源程序,正在努力成爲JSR-107開源規範,JSR-107規範已經不少年沒改變了。這個版本仍然是構建在最初的功能定義上。
  
  官方網站 http://jcache.sourceforge.net/
  
  ShiftOne 
  
  ShiftOne Java Object Cache是一個執行一系列嚴格的對象緩存策略的Java lib,就像一個輕量級的配置緩存工做狀態的框架。
  
  官方網站 http://jocache.sourceforge.net/
  
  SwarmCache 
  SwarmCache是一個簡單且有效的分佈式緩存,它使用IP multicast與同一個局域網的其餘主機進行通信,是特別爲集羣和數據驅動web應用程序而設計的。SwarmCache可以讓典型的讀操做大大超過寫操做的這類應用提供更好的性能支持。
  SwarmCache使用JavaGroups來管理從屬關係和分佈式緩存的通信。
  官方網站 http://swarmcache.sourceforge.net
  
  TreeCache / JBossCache 
  JBossCache是一個複製的事務處理緩存,它容許你緩存企業級應用數據來更好的改善性能。緩存數據被自動複製,讓你輕鬆進行JBoss服務器之間的集羣工做。JBossCache可以經過JBoss應用服務或其餘J2EE容器來運行一個MBean服務,固然,它也能獨立運行。
  
  JBossCache包括兩個模塊:TreeCache和TreeCacheAOP。
  
  TreeCache --是一個樹形結構複製的事務處理緩存。
  
  TreeCacheAOP --是一個「面向對象」緩存,它使用AOP來動態管理POJO(Plain Old Java Objects)
  
  注:AOP是OOP的延續,是Aspect Oriented Programming的縮寫,意思是面向方面編程。
  
  官方網站 http://www.jboss.org/products/jbosscache
  
  WhirlyCache 程序員

        Whirlycache是一個快速的、可配置的、存在於內存中的對象的緩存。它可以經過緩存對象來加快網站或應用程序的速度,不然就必須經過查詢數據庫或其餘代價較高的處理程序來創建。web

       

        Memcachedredis

        Memcached 是一個高性能的分佈式內存對象緩存系統,用於動態Web應用以減輕數據庫負載。它經過在內存中緩存數據和對象來減小讀取數據庫的次數,從而提升動態、數據庫驅動網站的速度。Memcached基於一個存儲鍵/值對的hashmap。其守護進程(daemon )是用C寫的,可是客戶端能夠用任何語言來編寫,並經過memcached協議與守護進程通訊。算法

       redissql

       redis是一個key-value存儲系統。和Memcached相似,它支持存儲的value類型相對更多,包括string(字符串)、list(鏈表)、set(集合)、zset(sorted set --有序集合)和hash(哈希類型)。這些數據類型都支持push/pop、add/remove及取交集並集和差集及更豐富的操做,並且這些操做都是原子性的。在此基礎上,redis支持各類不一樣方式的排序。與memcached同樣,爲了保證效率,數據都是緩存在內存中。區別的是redis會週期性的把更新的數據寫入磁盤或者把修改操做寫入追加的記錄文件,而且在此基礎上實現了master-slave(主從)同步。數據庫

Redis 是一個高性能的key-value數據庫。 redis的出現,很大程度補償了memcached這類key/value存儲的不足,在部 分場合能夠對關係數據庫起到很好的補充做用。它提供了Python,Ruby,Erlang,PHP客戶端,使用很方便。apache

Redis支持主從同步。數據能夠從主服務器向任意數量的從服務器上同步,從服務器能夠是關聯其餘從服務器的主服務器。這使得Redis可執行單層樹複製。從盤能夠有意無心的對數據進行寫操做。因爲徹底實現了發佈/訂閱機制,使得從數據庫在任何地方同步樹時,可訂閱一個頻道並接收主服務器完整的消息發佈記錄。同步對讀取操做的可擴展性和數據冗餘頗有幫助。

相關文章
相關標籤/搜索