memcache與EHcache的選擇java
使用緩存的原則就是:儘可能用低開銷的計算代替高開銷的計算。好比直接從數據庫查詢的開銷要遠高於內存中的計算返回,網絡請求要遠高於本地(同一VM中)請求。node
Memcache:分佈式內存對象緩存系統,佔用其餘機子的內存。不少互聯網,負載均衡三臺(以三臺爲例)web服務器能夠共享一臺Memcache的資源。傳遞的信息以鍵值對的形式存儲。傳遞的數據要實現序列化。git
Oscache:頁面級緩存(網上強調最多的東西),佔用本機的內存資源。可 以選擇緩存到硬盤,如存取到硬盤重啓服務也可從新得到上次持久化的資源,而若是緩存到內存就不行。通常不必緩存到硬盤,由於I/O操做也是比較耗資源,和從數據庫取每每優點很小。Oscache存取數據的做用域分爲application和session兩種。github
EhCache:Hibernate緩存,DAO緩存,安全性憑證緩存(Acegi),Web緩存,應用持久化和分佈式緩存。web
EhCache在默認狀況下,即在用戶未提供自身配置文件ehcache.xml或ehcache-failsafe.xml時,EhCache會依據其自身Jar存檔包含的ehcache-failsafe.xml文件所定製的策略來管理緩存。若是用戶在classpath下提供了ehcache.xml或ehcache-failsafe.xml文件,那麼EhCache將會應用這個文件。若是兩個文件同時提供,那麼EhCache會使用ehcache.xml文件的配置。EhCache默認內容以下:算法
<ehcache> <diskStore path="C:\Acegi6" /> <defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" maxElementsOnDisk="10000000" diskPersistent="false" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU"/> </ehcache>
緩存有三個做用範圍:事務、應用、集羣。事務級緩存在session中有效;應用級緩存在多個session中可共享,所以儘量只在read only型應用中使用,而集羣緩存就須要在各個節點上進行緩存同步。spring
Ehcache中,這些都是在同一個應用的前提條件下的,若是是多個應用在數據層整合,那麼任何一個範圍都有可能出現問題。尤爲是Ehcache,是一個進程內的 (in process)的緩存方案,受Spring管理,每一個Web App的緩存相互獨立(拋開ClassLoader Share),基本上不可能實現多應用緩存共享。即便使用消息中間件進行監聽,也不是一個完美的解決方案。數據庫
infoQ裏有一篇文章講述了在java的工做需求中memcached超過了terracotta’s Ehcache以及oracle’s Coherence 緩存框架, Memcached surpasses EhCache and Coherence in Java Job Demand.緩存
Memcache與Ehcache的一個對比表格:安全
項目 |
Memcache |
Ehcache |
分佈式 |
不徹底,集羣默認不實現 |
支持 |
集羣 |
可經過客戶端實現 |
支持(默認是異步同步) |
持久化 |
可經過第三方應用實現,如sina研發的memcachedb,將cache的數據保存到[url=]Berkerly DB[/url] |
支持。持久化到本地硬盤,生成一個.data和.index文件。cache初始化時會自動查找這兩個文件,將數據放入cache |
效率 |
高 |
高於Memcache |
容災 |
可經過客戶端實現。 |
支持 |
緩存數據方式 |
緩存在memcached server向系統申請的內存中 |
能夠緩存在內存(JVM中),也能夠緩存在硬盤。經過CacheManager管理cache。多個CacheManager可配置在一個JVM內,CacheManager可管理多個cache。 |
緩存過時移除策略 |
LRU |
[url=]LRU([/url]默認),FIFO,LFU |
缺點 |
功能不完善,相對於Ehcache效率低 |
只適用於java體系,只能用java編寫客戶端 |
優勢 |
簡潔,靈活,全部支持socket的語言都能編寫其客戶端 |
效率高。功能強大。 |
有關Ehcache更詳細的信息 http://ehcache.org/documentation或http://192.168.2.159/?p=132 。
本地緩存與遠程緩存
根據緩存和應用的耦合程度將其劃分爲Local Cache和Remote Cache。
Local Cache是指包含在應用之中的緩存組件,如Ehcache, Oscache.
Remote Cache指和應用解耦,在應用以外的緩存組件,如Memcached
Local Cache最大的優勢是應用和Cache在同一進程內部,請求緩存很是快速,徹底不須要網絡開銷,因此單應用,不須要集羣,或者集羣時Cache node不須要互相通知的狀況下使用比較合適。
缺點:多個應用程序沒法直接共享緩存,應用集羣的狀況下這個問題就更加明顯(好像是廢話= =)
Cache的類別:
本地緩存:從最簡單的Map到Ehcache單機版都屬於一類。
分佈式緩存:分佈在不一樣JVM的Cache能夠互相同步與備份,如JBossCache和Oracle那個天價的產品。
集中式緩存:最著名的表明是Memcache,Terracotta其實也屬於透明的集中式架構。
建議Ehcache單機使用,由於Terracotta收購後在分佈式緩存中必然側重於TC,JGroup等廣播通知方式已中止發展。注意:顯示聲明的Cache項並不會默認從DefaultCache節點繼承屬性,必須從新聲明或使用Ehcache內部的默認值。
Memcached是一種集中式Cache,支持分佈式橫向擴展。
集中式架構:
1.節點均衡的網狀(JBoss Tree Cache),利用JGroup的多廣播通訊機制來同步數據。
2.Maste-Slaves模式(分佈式文件系統),由Master來管理slave,如何選擇slave,如何遷移數據,都是由Master來完成,可是Master自己也存在單點問題。
應用點:
小對象的緩存(用戶的token,權限信息,資源信息),小的靜態資源緩存,SQL結果的緩存。
應對高併發訪問的應用,本地緩存採用EHCache,外部共享緩存採用Memcached,二者集成結合使用,參考示例見相關連接及svn checkout ehmem 示例。
Memcached詳細探討
Memcached介紹及分析
Memcached 是一種集中式 Cache,支持分佈式橫向擴展。經過在內存裏維護一個統一的巨大的hash表,Memcached可以用來存儲各類格式的數據,包括圖像、視頻、文件以及數據庫檢索的結果等。
Memcached服務端自己是單實例的,只是在客戶端實現過程當中能夠根據存儲的主鍵做分區存儲,而這個區就是Memcached服務端的一個或者多個實例,若是將客戶端也囊括到Memcached中,那麼能夠部分概念上說是集中式的。其實回顧一下集中式的構架,無非兩種狀況:1.節點均衡的網狀(JBoss Tree Cache),利用JGroup的多播通訊機制來同步數據。2.Master-Slaves模式(分佈式文件系統),由Master來管理Slave,如何選擇Slave,如何遷移數據,都是由Master來完成,可是Master自己也存在單點問題。
Memcached內存分配機制:首先要說明的是Memcached支持最大的存儲對象爲1M。key的長度小於250字符;像vmware, xen這類虛擬化技術並不適合運行memcached; Memcached未提供任何安全策略,僅僅經過telnet就能夠訪問到memcached, Memcached Java客戶端代碼的人就會了解其實客戶端的事情很簡單,就是要有一套高性能的 Socket通訊框架以及對 Memcached 的私有協議實現的接口。
在基於分佈式緩存的應用中,要確保每一個緩存中的數據徹底的一致是不可能的,總會存在這樣那樣的問題,即便像memcached,也由於沒有commit機制,可能出現一個node上先放入cache,而最後transaction回滾,但其餘的cache node已經爲其餘用戶提供了這個數據。
memcached的一些特色:
一、請求由client端進行處理,client端維護着一個memcached服務器列表,根據用戶的請求將響應指向不一樣的memcached服務器;(也就是說,每一個緩衝值,在全部服務器中只保持着一份copy,不像ehcache每一個服務器中都有)
二、memcached對CPU的要求不高,但對內存要求較高,所以能夠與webapp server安裝在一塊兒,互補(web app server是CPU要求高,內存要求低)
三、能夠動態地,甚至無限地增長memcached服務器的數量
首先memcached是獨立的服務器組件,獨立於應用系統,從客戶端保存和讀取對象到memcached是必須經過網絡傳輸,由於網絡傳輸都是二進制的數據,因此全部的對象都必須通過序列化,不然沒法存儲到memcahced的服務器端。
memcached採用 slab 內存處理機制
slab源於Jeff Bonwick 爲 SunOS 操做系統首次引入的一種內存處理機制,SLAB的設計理念是基於對象緩衝的,基本想法是避免重複大量的初始化和清理操做。SLAB主要能夠用於頻繁分配釋放的內存對象。若是是採用系統自帶的 malloc/free話,反覆地操做會形成大量內存碎片,操做系統將會花費大量的時間去查找連續的內存塊來知足malloc 的請求。
Memcached爲了提升內存的分配和回收效率,採用了slab和dump分區的概念。Memcached一大優點就是可以充分利用Memory資源,將同機器或者不一樣機器的Memcached服務端組合成爲對客戶端看似統一的存儲空間,Memcached能夠在一臺機器上開多個端口做爲服務端多個實例,也能夠在多臺機器上開多個服務實例,而slab就是Memcached的服務端。
如下是對cache的配置示例:
<?xml version="1.0" encoding="UTF-8"?> <memcached> <client name="mclient0" compressEnable="true" defaultEncoding="UTF-8" socketpool="pool0"> <!--errorHandler></errorHandler--> </client> <client name="mclient1" compressEnable="true" defaultEncoding="UTF-8" socketpool="pool1"> <!--errorHandler></errorHandler--> </client> <client name="mclient11" compressEnable="true" defaultEncoding="UTF-8" socketpool="pool11"> <!--errorHandler></errorHandler--> </client> <socketpool name="pool0" failover="true" initConn="10" minConn="5" maxConn="250" maintSleep="0" nagle="false" socketTO="3000" aliveCheck="true"> <servers>192.168.2.159:13000,192.168.2.159:13001,192.168.2.159:13002</servers> </socketpool> <socketpool name="pool1" failover="true" initConn="10" minConn="5" maxConn="250" maintSleep="0" nagle="false" socketTO="3000" aliveCheck="true"> <servers>192.168.2.159:13000</servers> </socketpool> <socketpool name="pool11" failover="true" initConn="10" minConn="5" maxConn="250" maintSleep="0" nagle="false" socketTO="3000" aliveCheck="true"> <servers>192.168.2.159:13000</servers> </socketpool> <cluster name="cluster1"> <memCachedClients>mclient1,mclient11</memCachedClients> </cluster> </memcached>
能夠看到其實pool纔是最終鏈接服務端的配置,看看pool0,它會鏈接10.2.225.210:13000,10.2.225.210:13001,10.2.225.210:13002這些機器和他們的端口,可是對於使用pool0的mclient0來講它僅僅只是知道有一個叫作mclient0的cache能夠保存數據。此時slab就有三個:10.2.225.210:13000和10.2.225.210:13001和10.2.225.210:13002。
當一個key:value要被放入到Memcached中,首先Memcached會根據key的hash算法獲取到hash值來選擇被分配的slab,而後根據value選擇適合的dump區。所謂dump區其實就是根據value的大小來將內存按照存儲單元內容大小分頁。這個是能夠配置Memcached的,例如Memcached將slab中的內存劃分紅4個dump,第一dump區存儲0-50k大小的數據,第二dump區存儲50-100k的數據,第三dump區存儲100-500k的數據,第四dump區存儲500-1000K的數據。那麼當key:value須要被寫入的時候,很容易定位到value所處的dump,分配內存給value。這種分dump模式簡化內存管理,加速了內存回收和分配。可是這裏須要注意的幾點就是,首先當你的應用場景中保存的數據大小離散度很高,那麼就不是很適合Memcached的這種分配模式,容易形成浪費,例如第一dump區已經滿了,第二第三dump區都仍是隻有一個數據,那麼第二第三dump區不會被回收,第二第三dump區的空間就浪費了。同時Memcached對於value的大小支持到1M,大於1M的內容不適合Memcached存儲。
memcached 中內存分配機制主要理念
1. 先爲分配相應的大塊內存,再在上面進行無縫小對象填充
2. 懶惰檢測機制,Memcached 不花過多的時間在檢測各個item對象是否超時,當 get獲取數據時,才檢查item對象是否應該刪除,你不訪問,我就不處理。
3. 懶惰刪除機制,在 memecached 中刪除一個 item對象的時候,並非從內存中釋放,而是單單的進行標記處理,再將其指針放入 slot回收插糟,下次分配的時候直接使用。
memcached的刪除機制
memcached內部不會監視記錄是否過時,而是在get時查看記錄的時間戳,檢查記錄是否過時, 這種技術被稱爲lazy(惰性)expiration.所以,memcached不會在過時監視上耗費CPU時間;memcached會優先使用已超時的記錄的空間,並使用LRU算法來分配空間,所以當memcached的內存空間不足,就從最近違背使用的記錄中搜索,並將空間分配給新的記錄;不過在某些狀況下LRU機制會形成某些麻煩,如你並不想要淘汰已被緩存過的記錄,能夠在memcached啓動時添加 -M 參數來禁止LRU,但這樣在memcached的內存用盡時,memcached會返回錯誤,是否使用LRU。
memcached的基本設置
啓動Memcache的服務器端
# /usr/local/bin/memcached -d -m 10 -u root -l 192.168.0.200 -p 12000 -c 256 -P /tmp/memcached.pid
Memcached一些經常使用的命令選項:
-p 監聽的端口
-l 鏈接的IP地址, 默認是本機
-d start 啓動memcached服務
-d restart 重起memcached服務
-d stop|shutdown 關閉正在運行的memcached服務
-d install 安裝memcached服務
-d uninstall 卸載memcached服務
-u 以的身份運行 (僅在以root運行的時候有效)
-m 最大內存使用,單位MB。默認64MB
-M 內存耗盡時返回錯誤,而不是刪除項
-c 最大同時鏈接數,默認是1024
-f 塊大小增加因子,默認是1.25
-n 最小分配空間,key+value+flags默認是48
-h 顯示幫助
memcache安裝及配置
包安裝
Debian / Ubuntu
apt-get install memcached
RedHat / Fedora
yum install memcached
源代碼安裝
tar –zxvf memcached-1.x.x.tar.gz
cd memcached-1.x.x
./configure
make && make test
sudo make install
備註:
1) 若是安裝過程當中出現依賴包(好比libevent)找不到的狀況,請安裝相應的依賴包。
2) 若是出現找不到so的狀況,經過ln –s /xxx/xxx.so /usr/lib/xxx.so作一個軟連接解決。
服務器端配置
使用如下命令進行啓動:
memcached –m 64 –l 10.11.11.33 –p 11211 –u xiajinxin
備註:
1)能夠經過命令memcache –h來查看全部命令參數
2)能夠經過追加參數-vv來進行調試輸出
3)能夠在同一臺機器上啓動多個memcached實例(端口不一樣)
具體能夠參考:http://code.google.com/p/memcached/wiki/NewConfiguringServer
集羣配置
因爲Memcached服務器與服務器之間沒有任何通信,而且不進行任何數據複製備份,因此當任何服務器節點出現故障時,會出現單點故障,若是須要實現HA,則須要經過另外的方式來解決。
經過Magent緩存代理,防止單點現象,緩存代理也能夠作備份,經過客戶端鏈接到緩存代理服務器,緩存代理服務器鏈接緩存鏈接服務器,緩存代理服務器能夠鏈接多臺Memcached機器能夠將每臺Memcached機器進行數據同步。若是其中一臺緩存服務器down機,系統依然能夠繼續工做,若是其中一臺Memcached機器down掉,數據不會丟失而且能夠保證數據的完整性。具體能夠參考:http://code.google.com/p/memagent/
memcache集羣的實現
memcached儘管是「分佈式」緩存服務器,但服務器端並無分佈式功能。各個memcached不會互相通訊以共享信息。那麼,怎樣進行分佈式呢?這徹底取決於客戶端的實現。
memcached的分佈式
Memcached做爲集中式Cache,就存在着集中式的致命問題:單點問題,Memcached支持多Instance分佈在多臺機器上,僅僅只是解決了數據所有丟失的問題,可是當其中一臺機器出錯之後,仍是會致使部分數據的丟失,一個籃子掉在地上仍是會把部分的雞蛋打破。
所以就須要實現一個備份機制,可以保證Memcached在部分失效之後,數據還可以依然使用,固然你們不少時候都用Cache不命中就去數據源獲取的策略,可是在SIP的場景中,若是部分信息找不到就去數據庫查找,那麼要把SIP弄垮真的是很容易,所以SIP對於Memcached中的數據認爲是可信的,所以作Cluster也是必要的。
1.應用傳入須要操做的key,經過CacheManager獲取配置在Cluster中的客戶端。
2.當得到Cache Client之後,執行Cache操做。
3. A.若是是讀取操做,當不能命中時去集羣其餘Cache客戶端獲取數據,若是獲取到數據,嘗試寫入到本次得到的Cache客戶端,並返回結果。(達到數據恢復的做用)
B.若是是更新操做,在本次獲取得Cache客戶端執行更新操做之後,當即返回,將更新集羣其餘機器命令提交給客戶端的異步更新線程對列去異步執行。(因爲若是是根據key來獲取Cache,那麼異步執行不會影響到此主鍵的查詢操做)
存在的問題:若是是設置了Timeout的數據,那麼在丟失之後被複制的過程當中就會變成永久有效的內容。
自定義cache接口實現與緩存框架解耦
因爲緩存系統有不少,如memcached,OSCache,Ehcache,JbossCache等,其中OSCache,Ehcache,JbossCache是用java實現的開源的緩存框架,一個大型項目功能模塊多,一般都集成了多個緩存系統。每套緩存框架都有各自的優缺點,隨着項目的不斷髮展,更換緩存系統也是頗有可能的,因此跟緩存系統的解耦是很是有必要的。
跟緩存進行解耦只需兩個工做:
1. 自定義緩存接口
2. 實現各個緩存框架的adapter(適配器模式)。
下面給出一個示意圖:
引用緩存策略
使用spring AOP 抽出一個專門緩存切面,切面主要作兩件事:
1、攔截類中定義的切入點;
2、進入切入點後,先從相應緩存中取key對應的value,若是取到值,就不執行切入點對應的方法;若是取不到值,則繼續執行原來方法。
key:包名類名方法名參數
value:該方法的返回值
windowns下使用
1.安裝與啓動
2.終端使用memcached
登陸到緩存服務器,而後在cmd命令行中鍵入
查看 Memcached 內部工做狀態
訪問訪問 Memcached :telnet 主機名 端口號
查看總狀態: 查看總狀態: stats stats
查看某項狀態: 查看某項狀態: stats curr_connections
選項 說明
add 僅當存儲空間中不存在鍵相同的數據時才保存
replace 僅當存儲空間中存在鍵相同的數據時才保存
set 與 add 和 replace 不一樣,不管什麼時候都保存
緩存管理事項
1. 安裝memcached
2. memcached實例管理
3. memcached緩存信息監控
相關連接:
memcached與ehcache使用示例項目:
https://github.com/yangjiandong/pm.git
轉自:http://blog.163.com/luowei505050@126/blog/static/11990720620128682726877/
EHCache:http://blog.163.com/luowei505050@126/blog/static/1199072062012330064353/