1. 程式人生 > >java中的快取技術該如何實現

java中的快取技術該如何實現

1快取為什麼要存在?
2快取可以存在於什麼地方?
3快取有哪些屬性?
4快取介質?

搞清楚這4個問題,那麼我們就可以隨意的通過應用的場景來判斷使用何種快取了.


1. 快取為什麼要存在?
一 般情況下,一個網站,或者一個應用,它的一般形式是,瀏覽器請求應用伺服器,應用伺服器做一堆計算後再請求資料庫,資料庫收到請求後再作一堆計算後把資料 返回給應用伺服器,應用伺服器再作一堆計算後把資料返回給瀏覽器.這個是一個標準流程.但是隨著互連網的普及,上網的人越來越多,網上的資訊量也越來越 多,在這兩個越來越多的情況下,我們的應用需要支撐的併發量就越來越多.然後我們的應用伺服器和資料庫伺服器所做的計算也越來越多,但是往往我們的應用服 務器資源是有限的,資料庫每秒中接受請求的次數也是有限的(誰叫俺們的硬碟轉速有限呢).如果利用有限的資源來提供儘可能大的吞吐量呢,一個辦法:減少計 算量,縮短請求流程(減少網路io或者硬碟io),這時候快取就可以大展手腳了.快取的基本原理就是打破上圖中所描繪的標準流程,在這個標準流程中,任何 一個環節都可以被切斷.請求可以從快取裡取到資料直接返回.這樣不但節省了時間,提高了響應速度,而且也節省了硬體資源.可以讓我們有限的硬體資源來服務 更多的使用者.


2 快取可以存在於什麼地方?
Java程式碼
  1. 瀏覽器---?瀏覽器和app之間---?分過層的app-?資料庫

瀏覽器---?瀏覽器和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 認為,快取的使用是架構師的必備技能,好的架構師能夠根據資料的型別,業務的場景來準確的判斷出使用何種型別的快取,並且如何使用這種型別的快取.在快取 的世界裡也沒有銀彈,目前還沒有一種快取可以解決任何的業務場景或者資料型別,如果這種技術出現了,那架構師就又更不值錢了.呵呵.

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是一個快速的、可配置的、存在於記憶體中的物件的快取。它能夠通過快取物件來加快網站或應用程式的速度,否則就必須通過查詢資料庫或其他代價較高的處理程式來建立。