天天看點

EhCache 分布式緩存/緩存叢集

開發環境:

System:Windows

JavaEE Server:tomcat5.0.2.8、tomcat6

JavaSDK: jdk6+

IDE:eclipse、MyEclipse 6.6

開發依賴庫:

JDK6、 JavaEE5、ehcache-core-2.5.2.jar

Email:[email protected]

<a href="http://hoojo.cnblogs.com/">http://hoojo.cnblogs.com/</a>

<a href="http://hoojo.blogjava.net/">http://hoojo.blogjava.net</a>

一、緩存系統簡介

EhCache 是一個純 Java 的程序内緩存架構,具有快速、精幹等特點,是 Hibernate 中預設的 CacheProvider。

EhCache 應用架構圖,下圖是 EhCache 在應用程式中的位置:

<a href="http://images.cnblogs.com/cnblogs_com/hoojo/201207/201207191626353745.jpg"></a>

<b>EhCache </b><b>的主要特性有:</b>

1. 快速、精幹; 2. 簡單; 3. 多種緩存政策; 4. 緩存資料有兩級:記憶體和磁盤,是以無需擔心容量問題; 5. 緩存資料會在虛拟機重新開機的過程中寫入磁盤; 6. 可以通過 RMI、可插入 API 等方式進行分布式緩存; 7. 具有緩存和緩存管理器的偵聽接口; 8. 支援多緩存管理器執行個體,以及一個執行個體的多個緩存區域; 9. 提供 Hibernate 的緩存實作;
由于 EhCache 是程序中的緩存系統,一旦将應用部署在叢集環境中,每一個節點維護各自的緩存資料,當某個節點對緩存資料進行更新,這些更新的資料無法在其它節點中共享,這不僅會降低節點運作的效率,而且會導緻資料不同步的情況發生。例如某個網站采用 A、B 兩個節點作為叢集部署,當 A 節點的緩存更新後,而 B 節點緩存尚未更新就可能出現使用者在浏覽頁面的時候,一會是更新後的資料,一會是尚未更新的資料,盡管我們也可以通過 Session Sticky 技術來将使用者鎖定在某個節點上,但對于一些互動性比較強或者是非 Web 方式的系統來說,Session Sticky 顯然不太适合。 是以就需要用到 EhCache 的叢集解決方案。

從1.2版本開始,Ehcache可以使用分布式的緩存了。<b>EhCache </b><b>從 1.7 </b><b>版本開始,支援五種叢集方案,分别是:</b>

• Terracotta • RMI • JMS • JGroups • EhCache Server 其中的三種最為常用叢集方式,分别是 RMI、JGroups 以及 EhCache Server 。本文主要介紹RMI的方式。 分布式這個特性是以plugin的方式實作的。Ehcache自帶了一些預設的分布式緩存插件實作,這些插件可以滿足大部分應用的需要。如果需要使用其他的插件那就需要自己開發了,開發者可以通過檢視distribution包裡的源代碼及JavaDoc來實作它。盡管不是必須的,在使用分布式緩存時了解一些ehcahce的設計思想也是有幫助的。這可以參看分布式緩存設計的頁面。以下的部分将展示如何讓分布式插件同ehcache一起工作。

下面列出的是一些分布式緩存中比較重要的方面:

• 你如何知道叢集環境中的其他緩存? • 分布式傳送的消息是什麼形式? • 什麼情況需要進行複制?增加(Puts),更新(Updates)或是失效(Expiries)? • 采用什麼方式進行複制?同步還是異步方式? 為了安裝分布式緩存,你需要配置一個PeerProvider、一個CacheManagerPeerListener, 它們對于一個CacheManager來說是全局的。每個進行分布式操作的cache都要添加一個cacheEventListener來傳送消息。

二、叢集緩存概念及其配置

隻有可序列化的元素可以進行複制。一些操作,比如移除,隻需要元素的鍵值而不用整個元素;在這樣的操作中即使元素不是可序列化的但鍵值是可序列化的也可以被複制。
Ehcache進行叢集的時候有一個cache組的概念。每個cache都是其他cache的一個peer,沒有主cache的存在。剛才我們問了一個問題:你如何知道叢集環境中的其他緩存?這個問題可以命名為成員發現(Peer Discovery)。 Ehcache提供了兩種機制用來進行成員發現,就像一輛汽車:手動檔和自動檔。要使用一個内置的成員發現機制要在ehcache的配置檔案中指定cacheManagerPeerProviderFactory元素的class屬性為 net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory。
自動的發現方式用TCP廣播機制來确定和維持一個廣播組。它隻需要一個簡單的配置可以自動的在組中添加和移除成員。在叢集中也不需要什麼優化伺服器的知識,這是預設推薦的。 成員每秒向群組發送一個“心跳”。如果一個成員 5秒種都沒有發出信号它将被群組移除。如果一個新的成員發送了一個“心跳”它将被添加進群組。 任何一個用這個配置安裝了複制功能的cache都将被其他的成員發現并辨別為可用狀态。 要設定自動的成員發現,需要指定ehcache配置檔案中cacheManagerPeerProviderFactory元素的properties屬性,就像下面這樣: peerDiscovery=automatic multicastGroupAddress=multicast address | multicast host name multicastGroupPort=port timeToLive=0-255 (timeToLive屬性詳見常見問題部分的描述)
假設你在叢集中有兩台伺服器。你希望同步sampleCache1和sampleCache2。每台獨立的伺服器都要有這樣的配置: 配置server1和server2
進行手動成員配置要知道每個監聽器的IP位址和端口。成員不能在運作時動态地添加和移除。在技術上很難使用廣播的情況下就可以手動成員發現,例如在叢集的伺服器之間有一個不能傳送廣播封包的路由器。你也可以用手動成員發現進行單向的資料複制,隻讓server2知道server1,而server1不知道server2。 配置手動成員發現,需要指定ehcache配置檔案中cacheManagerPeerProviderFactory的properties屬性,像下面這樣: peerDiscovery=manual rmiUrls=//server:port/cacheName, //server:port/cacheName ... rmiUrls配置的是伺服器cache peers的清單。注意不要重複配置。
假設你在叢集中有兩台伺服器。你要同步sampleCache1和sampleCache2。下面是每個伺服器需要的配置: 配置server1

  配置server2

每個CacheManagerPeerListener監聽從成員們發向目前CacheManager的消息。配置CacheManagerPeerListener需要指定一個CacheManagerPeerListenerFactory,它以插件的機制實作,用來建立CacheManagerPeerListener。 cacheManagerPeerListenerFactory的屬性有: class – 一個完整的工廠類名。 properties – 隻對這個工廠有意義的屬性,使用逗号分隔。 Ehcache有一個内置的基于RMI的分布系統。它的監聽器是RMICacheManagerPeerListener,這個監聽器可以用 RMICacheManagerPeerListenerFactory來配置。

有效的屬性是: hostname (可選) – 運作監聽器的伺服器名稱。标明了做為叢集群組的成員的位址,同時也是你想要控制的從叢集中接收消息的接口。 在CacheManager初始化的時候會檢查hostname是否可用。 如果hostName不可用,CacheManager将拒絕啟動并抛出一個連接配接被拒絕的異常。 如果指定,hostname将使用InetAddress.getLocalHost().getHostAddress()來得到。 警告:不要将localhost配置為本地位址127.0.0.1,因為它在網絡中不可見将會導緻不能從遠端伺服器接收資訊進而不能複制。在同一台機器上有多個CacheManager的時候,你應該隻用localhost來配置。 port – 監聽器監聽的端口。 socketTimeoutMillis (可選) – Socket逾時的時間。預設是2000ms。當你socket同步緩存請求位址比較遠,不是本地區域網路。你可能需要把這個時間配置大些,不然很可能延時導緻同步緩存失敗。

每個要進行同步的cache都需要設定一個用來向CacheManagerr的成員複制消息的緩存事件監聽器。這個工作要通過為每個cache的配置增加一個cacheEventListenerFactory元素來完成。

class – 使用net.sf.ehcache.distribution.RMICacheReplicatorFactory 這個工廠支援以下屬性: replicatePuts=true | false – 當一個新元素增加到緩存中的時候是否要複制到其他的peers. 預設是true。 replicateUpdates=true | false – 當一個已經在緩存中存在的元素被覆寫時是否要進行複制。預設是true。 replicateRemovals= true | false – 當元素移除的時候是否進行複制。預設是true。 replicateAsynchronously=true | false – 複制方式是異步的(指定為true時)還是同步的(指定為false時)。預設是true。 replicatePutsViaCopy=true | false – 當一個新增元素被拷貝到其他的cache中時是否進行複制指定為true時為複制,預設是true。 replicateUpdatesViaCopy=true | false – 當一個元素被拷貝到其他的cache中時是否進行複制(指定為true時為複制),預設是true。 你可以使用ehcache的預設行為進而減少配置的工作量,預設的行為是以異步的方式複制每件事;你可以像下面的例子一樣減少RMICacheReplicatorFactory的屬性配置:

由于在Windows上安裝Tomcat預設是裝在“Program Files”檔案夾裡的,是以這個問題經常發生。
自動的peer discovery與廣播息息相關。廣播可能被路由阻攔,像Xen和VMWare這種虛拟化的技術也可以阻攔廣播。如果這些都打開了,你可能還在要将你的網卡的相關配置打開。一個簡單的辦法可以告訴廣播是否有效, 那就是使用ehcache remote debugger來看“心跳”是否可用。
你可以通過設定badly misnamed time to live來控制廣播傳播的距離。用廣播IP協定時,timeToLive的值指的是資料包可以傳遞的域或是範圍。約定如下: 0是限制在同一個伺服器 1是限制在同一個子網 32是限制在同一個網站 64是限制在同一個region 128是限制在同一個大洲 255是不限制 譯者按:上面這些資料翻譯的不夠準确,請讀者自行尋找原文了解吧。 在Java實作中預設值是1,也就是在同一個子網中傳播。改變timeToLive屬性可以限制或是擴充傳播的範圍。

三、 RMI方式緩存叢集/配置分布式緩存

RMI 是 Java 的一種遠端方法調用技術,是一種點對點的基于 Java 對象的通訊方式。EhCache 從 1.2 版本開始就支援 RMI 方式的緩存叢集。在叢集環境中 EhCache 所有緩存對象的鍵和值都必須是可序列化的,也就是必須實作 java.io.Serializable 接口,這點在其它叢集方式下也是需要遵守的。

     下圖是 RMI 叢集模式的結構圖:

采用 RMI 叢集模式時,叢集中的每個節點都是對等關系,并不存在主節點或者從節點的概念,是以節點間必須有一個機制能夠互相認識對方,必須知道其它節點的資訊,包括主機位址、端口号等。EhCache 提供兩種節點的發現方式:手工配置和自動發現。手工配置方式要求在每個節點中配置其它所有節點的連接配接資訊,一旦叢集中的節點發生變化時,需要對緩存進行重新配置。 由于 RMI 是 Java 中内置支援的技術,是以使用 RMI 叢集模式時,無需引入其它的 Jar 包,EhCache 本身就帶有支援 RMI 叢集的功能。使用 RMI 叢集模式需要在 ehcache.xml 配置檔案中定義 cacheManagerPeerProviderFactory 節點。

<b></b> 

<b>      分布式同步緩存要讓這邊的</b><b>cache</b><b>知道對方的</b><b>cache</b><b>,叫做</b><b>Peer Discovery</b><b>(成員發現)</b><b> EHCache</b><b>實作成員發現的方式有兩種:</b><b></b>

<b>1、</b><b>手動查找</b><b></b>

A、 在ehcache.xml中配置PeerDiscovery成員發現對象       Server1配置,配置本地hostName、port是400001,分别監聽192.168.8.32:400002的mobileCache和192.168.5.231:400003 的mobileCache。注意這裡的mobileCache是緩存的名稱,分别對應着server2、server3的cache的配置。

以上注意cacheManagerPeerProviderFactory元素出現的位置在diskStore下   同樣在你的另外2台伺服器上增加配置 Server2,配置本地host,port為400002,分别同步192.168.8.9:400001的mobileCache和192.168.5.231:400003的mobileCache

Server3,配置本地host,port為400003,分别同步192.168.8.9:400001的mobileCache緩存和192.168.8.32:400002的mobileCache緩存

這樣就在三台不同的伺服器上配置了手動查找cache的PeerProvider成員發現的配置了。 值得注意的是你在配置rmiUrls的時候要特别注意url不能重複出現,并且端口、位址都是對的。 如果指定,hostname将使用InetAddress.getLocalHost().getHostAddress()來得到。 警告:不要将localhost配置為本地位址127.0.0.1,因為它在網絡中不可見将會導緻不能從遠端伺服器接收資訊進而不能複制。在同一台機器上有多個CacheManager的時候,你應該隻用localhost來配置。   B、 下面配置緩存和緩存同步監聽,需要在每台伺服器中的ehcache.xml檔案中增加cache配置和cacheEventListenerFactory、cacheLoaderFactory的配置

  C、 這樣就完成了3台伺服器的配置,下面給出server1的完整的ehcache.xml的配置

<b>2、</b><b>自動發現</b><b></b>

自動發現配置和手動查找的方式有一點不同,其他的地方都基本是一樣的。同樣在ehcache.xml中增加配置,配置如下

其他的配置和手動查找方式的配置是一樣的,這裡就不再贅述了。關于ehcache的其他緩存配置方式這裡将不再介紹,大家可以自己去研究。可以參考:

本文轉自hoojo部落格園部落格,原文連結:http://www.cnblogs.com/hoojo/archive/2012/07/19/2599534.html,如需轉載請自行聯系原作者