熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

EhCache 分布式緩存/緩存集群

2013-11-23 18:46:35  來源: Java核心技術 

  緩存系統簡介
   
    EhCache 是一個純 Java 的進程內緩存框架具有快速精干等特點是 Hibernate 中默認的 CacheProvider
   
    EhCache 應用架構圖下圖是 EhCache 在應用程序中的位置

   
    
    EhCache 的主要特性有
   
    快速精干
   
    簡單
   
    多種緩存策略
   
    緩存數據有兩級內存和磁盤因此無需擔心容量問題
   
    緩存數據會在虛擬機重啟的過程中寫入磁盤
   
    可以通過 RMI可插入 API 等方式進行分布式緩存
   
    具有緩存和緩存管理器的偵聽接口
   
    支持多緩存管理器實例以及一個實例的多個緩存區域
   
    提供 Hibernate 的緩存實現
   
    由於 EhCache 是進程中的緩存系統一旦將應用部署在集群環境中每一個節點維護各自的緩存數據當某個節點對緩存數據進行更新這些更新的數據無法在其它節點中共享這不僅會降低節點運行的效率而且會導致數據不同步的情況發生例如某個網站采用 AB 兩個節點作為集群部署當 A 節點的緩存更新後而 B 節點緩存尚未更新就可能出現用戶在浏覽頁面的時候一會是更新後的數據一會是尚未更新的數據盡管我們也可以通過 Session Sticky 技術來將用戶鎖定在某個節點上但對於一些交互性比較強或者是非 Web 方式的系統來說Session Sticky 顯然不太適合
   
    所以就需要用到 EhCache 的集群解決方案
   
    從版本開始Ehcache可以使用分布式的緩存了EhCache 從 版本開始支持五種集群方案分別是
   
    ? Terracotta
   
    ? RMI
   
    ? JMS
   
    ? JGroups
   
    ? EhCache Server
   
    其中的三種最為常用集群方式分別是 RMIJGroups 以及 EhCache Server 本文主要介紹RMI的方式
   
    分布式這個特性是以plugin的方式實現的Ehcache自帶了一些默認的分布式緩存插件實現這些插件可以滿足大部分應用的需要如果需要使用其他的插件那就需要自己開發了開發者可以通過查看distribution包裡的源代碼及JavaDoc來實現它盡管不是必須的在使用分布式緩存時理解一些ehcahce的設計思想也是有幫助的這可以參看分布式緩存設計的頁面以下的部分將展示如何讓分布式插件同ehcache一起工作
   
    下面列出的是一些分布式緩存中比較重要的方面
   
    ? 你如何知道集群環境中的其他緩存?
   
    ? 分布式傳送的消息是什麼形式?
   
    ? 什麼情況需要進行復制?增加(Puts)更新(Updates)或是失效(Expiries)?
   
    ? 采用什麼方式進行復制?同步還是異步方式?
   
    為了安裝分布式緩存你需要配置一個PeerProvider一個CacheManagerPeerListener
   
    它們對於一個CacheManager來說是全局的每個進行分布式操作的cache都要添加一個cacheEventListener來傳送消息


   
集群緩存概念及其配置
   
    正確的元素類型
   
    只有可序列化的元素可以進行復制一些操作比如移除只需要元素的鍵值而不用整個元素在這樣的操作中即使元素不是可序列化的但鍵值是可序列化的也可以被復制
   
    成員發現(Peer Discovery)
   
    Ehcache進行集群的時候有一個cache組的概念每個cache都是其他cache的一個peer沒有主cache的存在剛才我們問了一個問題你如何知道集群環境中的其他緩存?這個問題可以命名為成員發現(Peer Discovery)
   
    Ehcache提供了兩種機制用來進行成員發現就像一輛汽車手動檔和自動檔要使用一個內置的成員發現機制要在ehcache的配置文件中指定cacheManagerPeerProviderFactory元素的class屬性為
   
    netsfehcachedistributionRMICacheManagerPeerProviderFactory
   
    自動的成員發現
   
    自動的發現方式用TCP廣播機制來確定和維持一個廣播組它只需要一個簡單的配置可以自動的在組中添加和移除成員在集群中也不需要什麼優化服務器的知識這是默認推薦的
   
    成員每秒向群組發送一個心跳如果一個成員 秒種都沒有發出信號它將被群組移除如果一個新的成員發送了一個心跳它將被添加進群組
   
    任何一個用這個配置安裝了復制功能的cache都將被其他的成員發現並標識為可用狀態
   
    要設置自動的成員發現需要指定ehcache配置文件中cacheManagerPeerProviderFactory元素的properties屬性就像下面這樣
   
    peerDiscovery=automatic
   
    multicastGroupAddress=multicast address | multicast host name
   
    multicastGroupPort=port
   
    timeToLive= (timeToLive屬性詳見常見問題部分的描述)
   
    示例
   
    假設你在集群中有兩台服務器你希望同步sampleCache和sampleCache每台獨立的服務器都要有這樣的配置
   
    配置server和server
   
    <cacheManagerPeerProviderFactoryclass=netsfehcachedistributionRMICacheManagerPeerProviderFactoryproperties=peerDiscovery=automatic multicastGroupAddress=/>multicastGroupPort= timeToLive=手動進行成員發現
   
    進行手動成員配置要知道每個監聽器的IP地址和端口成員不能在運行時動態地添加和移除在技術上很難使用廣播的情況下就可以手動成員發現例如在集群的服務器之間有一個不能傳送廣播報文的路由器你也可以用手動成員發現進行單向的數據復制只讓server知道server而server不知道server
   
    配置手動成員發現需要指定ehcache配置文件中cacheManagerPeerProviderFactory的properties屬性像下面這樣
   
    peerDiscovery=manual rmiUrls=//server:port/cacheName //server:port/cacheName …
   
    rmiUrls配置的是服務器cache peers的列表注意不要重復配置
   
    示例
   
    假設你在集群中有兩台服務器你要同步sampleCache和sampleCache下面是每個服務器需要的配置
   
    配置server
   
    <cacheManagerPeerProviderFactoryclass=netsfehcachedistributionRMICacheManagerPeerProviderFactoryproperties=peerDiscovery=manual/>rmiUrls=//server:/sampleCache|//server:/sampleCache
   
    配置server
   
    <cacheManagerPeerProviderFactoryclass=netsfehcachedistributionRMICacheManagerPeerProviderFactoryproperties=peerDiscovery=manual/>rmiUrls=//server:/sampleCache|//server:/sampleCache配置CacheManagerPeerListener
   
    每個CacheManagerPeerListener監聽從成員們發向當前CacheManager的消息配置CacheManagerPeerListener需要指定一個CacheManagerPeerListenerFactory它以插件的機制實現用來創建CacheManagerPeerListener
   
    cacheManagerPeerListenerFactory的屬性有
   
    class – 一個完整的工廠類名
   
    properties – 只對這個工廠有意義的屬性使用逗號分隔
   
    Ehcache有一個內置的基於RMI的分布系統它的監聽器是RMICacheManagerPeerListener這個監聽器可以用
   
    RMICacheManagerPeerListenerFactory來配置
   
    <cacheManagerPeerListenerFactoryclass=netsfehcachedistributionRMICacheManagerPeerListenerFactoryproperties=hostName=localhost port=/>socketTimeoutMillis=有效的屬性是
   
    hostname (可選) – 運行監聽器的服務器名稱標明了做為集群群組的成員的地址同時也是你想要控制的從集群中接收消息的接口


    
    在CacheManager初始化的時候會檢查hostname是否可用
   
    如果hostName不可用CacheManager將拒絕啟動並拋出一個連接被拒絕的異常
   
    如果指定hostname將使用InetAddressgetLocalHost()getHostAddress()來得到
   
    警告不要將localhost配置為本地地址因為它在網絡中不可見將會導致不能從遠程服務器接收信息從而不能復制在同一台機器上有多個CacheManager的時候你應該只用localhost來配置
   
    port – 監聽器監聽的端口
   
    socketTimeoutMillis (可選) – Socket超時的時間默認是ms當你socket同步緩存請求地址比較遠不是本地局域網你可能需要把這個時間配置大些不然很可能延時導致同步緩存失敗
   
    配置CacheReplicators
   
    每個要進行同步的cache都需要設置一個用來向CacheManagerr的成員復制消息的緩存事件監聽器這個工作要通過為每個cache的配置增加一個cacheEventListenerFactory元素來完成
   
    <! Sample cache named sampleCache ><cache name=sampleCachemaxElementsInMemory=eternal=falsetimeToIdleSeconds=timeToLiveSeconds=overflowToDisk=false><cacheEventListenerFactory class=netsfehcachedistributionRMICacheReplicatorFactoryproperties=replicateAsynchronously=truereplicatePuts=true replicateUpdates=true replicateUpdatesViaCopy=false replicateRemovals=true /></cache>class – 使用netsfehcachedistributionRMICacheReplicatorFactory
   
    這個工廠支持以下屬性
   
    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的屬性配置
   
    <! Sample cache named sampleCache All missing RMICacheReplicatorFactory properties default to true ><cache name=sampleCachemaxElementsInMemory=eternal=trueoverflowToDisk=falsememoryStoreEvictionPolicy=LFU><cacheEventListenerFactory class=netsfehcachedistributionRMICacheReplicatorFactory/></cache>
   
    常見的問題
   
    Windows上的Tomcat
   
    有一個Tomcat或者是JDK的bug在tomcat啟動時如果tomcat的安裝路徑中有空格的話在啟動時RMI監聽器會失敗參見bin/wa?A=ind&L=rmiusers&P=doc/faqhowtobugs/l
   
    由於在Windows上安裝Tomcat默認是裝在Program Files文件夾裡的所以這個問題經常發生
   
    廣播阻斷
   
    自動的peer discovery與廣播息息相關廣播可能被路由阻攔像Xen和VMWare這種虛擬化的技術也可以阻攔廣播如果這些都打開了你可能還在要將你的網卡的相關配置打開一個簡單的辦法可以告訴廣播是否有效
   
    那就是使用ehcache remote debugger來看心跳是否可用
   
    廣播傳播的不夠遠或是傳得太遠
   
    你可以通過設置badly misnamed time to live來控制廣播傳播的距離用廣播IP協議時timeToLive的值指的是數據包可以傳遞的域或是范圍約定如下
   
    是限制在同一個服務器
   
    是限制在同一個子網
   
    是限制在同一個網站
   
    是限制在同一個region
   
    是限制在同一個大洲
   
    是不限制
   
    譯者按上面這些資料翻譯的不夠准確請讀者自行尋找原文理解吧
   
    在Java實現中默認值是也就是在同一個子網中傳播改變timeToLive屬性可以限制或是擴展傳播的范圍
   


RMI方式緩存集群/配置分布式緩存
   
    RMI 是 Java 的一種遠程方法調用技術是一種點對點的基於 Java 對象的通訊方式EhCache 從 版本開始就支持 RMI 方式的緩存集群在集群環境中 EhCache 所有緩存對象的鍵和值都必須是可序列化的也就是必須實現 javaioSerializable 接口這點在其它集群方式下也是需要遵守的
   
    下圖是 RMI 集群模式的結構圖

   
    
    采用 RMI 集群模式時集群中的每個節點都是對等關系並不存在主節點或者從節點的概念因此節點間必須有一個機制能夠互相認識對方必須知道其它節點的信息包括主機地址端口號等EhCache 提供兩種節點的發現方式手工配置和自動發現手工配置方式要求在每個節點中配置其它所有節點的連接信息一旦集群中的節點發生變化時需要對緩存進行重新配置
   
    由於 RMI 是 Java 中內置支持的技術因此使用 RMI 集群模式時無需引入其它的 Jar 包EhCache 本身就帶有支持 RMI 集群的功能使用 RMI 集群模式需要在 ehcachexml 配置文件中定義 cacheManagerPeerProviderFactory 節點
   
    分布式同步緩存要讓這邊的cache知道對方的cache叫做Peer Discovery(成員發現) EHCache實現成員發現的方式有兩種
   
    手動查找
   
    A 在ehcachexml中配置PeerDiscovery成員發現對象
   
    Server配置配置本地hostNameport是分別監聽:的mobileCache和: 的mobileCache注意這裡的mobileCache是緩存的名稱分別對應著serverserver的cache的配置
   
    <?xml version= encoding=gbk?><ehcache xmlns:xsi=instance xsi:noNamespaceSchemaLocation=ehcachexsd>
   
    <diskStore path=javaiotmpdir/>
   
    <!
   
    集群多台服務器中的緩存這裡是要同步一些服務器的緩存
   
    server hostName: port: cacheName:mobileCache
   
    server hostName: port: cacheName:mobileCache
   
    server hostName: port: cacheName:mobileCache
   
    注意每台要同步緩存的服務器的RMI通信socket端口都不一樣在配置的時候注意設置
   
    >
   
    <! server 的cacheManagerPeerProviderFactory配置 >
   
    <cacheManagerPeerProviderFactory
   
    class=netsfehcachedistributionRMICacheManagerPeerProviderFactory
   
    properties=hostName=localhost
   
    port=
   
    socketTimeoutMillis=
   
    peerDiscovery=manual
   
    rmiUrls=//:/mobileCache|//:/mobileCache
   
    /></ehcache>以上注意cacheManagerPeerProviderFactory元素出現的位置在diskStore下
   


    同樣在你的另外台服務器上增加配置
   
    Server配置本地hostport為分別同步:的mobileCache和:的mobileCache
   
    <! server 的cacheManagerPeerProviderFactory配置 ><cacheManagerPeerProviderFactory
   
    class=netsfehcachedistributionRMICacheManagerPeerProviderFactory
   
    properties=hostName=localhost
   
    port=
   
    socketTimeoutMillis=
   
    peerDiscovery=manual
   
    rmiUrls=//:/mobileCache|//:/mobileCache/>Server配置本地hostport為分別同步:的mobileCache緩存和:的mobileCache緩存
   
    <! server 的cacheManagerPeerProviderFactory配置 ><cacheManagerPeerProviderFactory
   
    class=netsfehcachedistributionRMICacheManagerPeerProviderFactory
   
    properties=hostName=localhost
   
    port=
   
    socketTimeoutMillis=
   
    peerDiscovery=manual
   
    rmiUrls=//:/mobileCache|//:/mobileCache/>這樣就在三台不同的服務器上配置了手動查找cache的PeerProvider成員發現的配置了 值得注意的是你在配置rmiUrls的時候要特別注意url不能重復出現並且端口地址都是對的
   
    如果指定hostname將使用InetAddressgetLocalHost()getHostAddress()來得到
   
    警告不要將localhost配置為本地地址因為它在網絡中不可見將會導致不能從遠程服務器接收信息從而不能復制在同一台機器上有多個CacheManager的時候你應該只用localhost來配置
   
    B 下面配置緩存和緩存同步監聽需要在每台服務器中的ehcachexml文件中增加cache配置和cacheEventListenerFactorycacheLoaderFactory的配置
   
    <defaultCache maxElementsInMemory= eternal=false timeToIdleSeconds= timeToLiveSeconds= overflowToDisk=false/><!
   
    配置自定義緩存
   
    maxElementsInMemory:緩存中允許創建的最大對象數
   
    eternal:緩存中對象是否為永久的如果是超時設置將被忽略對象從不過期
   
    timeToIdleSeconds:緩存數據空閒的最大時間也就是說如果有一個緩存有多久沒有被訪問就會被銷毀如果該值是 就意味著元素可以停頓無窮長的時間
   
    timeToLiveSeconds:緩存數據存活的時間緩存對象最大的的存活時間超過這個時間就會被銷毀這只能在元素不是永久駐留時有效如果該值是就意味著元素可以停頓無窮長的時間
   
    overflowToDisk:內存不足時是否啟用磁盤緩存
   
    memoryStoreEvictionPolicy:緩存滿了之後的淘汰算法
   
    每一個小時更新一次緩存(小時過期) ><cache name=mobileCache
   
    maxElementsInMemory=
   
    eternal=false
   
    overflowToDisk=true
   
    timeToIdleSeconds=
   
    timeToLiveSeconds=
   
    memoryStoreEvictionPolicy=LFU>
   
    <!
   
    RMI緩存分布同步查找 class使用netsfehcachedistributionRMICacheReplicatorFactory
   
    這個工廠支持以下屬性
   
    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
   
    asynchronousReplicationIntervalMillis=
   
    >
   
    <! 監聽RMI同步緩存對象配置 注冊相應的的緩存監聽類用於處理緩存事件如putremoveupdate和expire >
   
    <cacheEventListenerFactory
   
    class=netsfehcachedistributionRMICacheReplicatorFactory
   
    properties=replicateAsynchronously=true />
   
    replicatePuts=true
   
    replicateUpdates=true
   
    replicateUpdatesViaCopy=false
   
    replicateRemovals=true
   
    <! 用於在初始化緩存以及自動設置 >
   
    <bootstrapCacheLoaderFactory class=netsfehcachebootstrapBootstrapCacheLoaderFactory/></cache>
   
    C 這樣就完成了台服務器的配置下面給出server的完整的ehcachexml的配置
   
    <?xml version= encoding=gbk?><ehcache xmlns:xsi=instance xsi:noNamespaceSchemaLocation=ehcachexsd>
   
    <diskStore path=javaiotmpdir/>
   
    <!
   


    集群多台服務器中的緩存這裡是要同步一些服務器的緩存
   
    server hostName: port: cacheName:mobileCache
   
    server hostName: port: cacheName:mobileCache
   
    server hostName: port: cacheName:mobileCache
   
    注意每台要同步緩存的服務器的RMI通信socket端口都不一樣在配置的時候注意設置
   
    >
   
    <! server 的cacheManagerPeerProviderFactory配置 >
   
    <cacheManagerPeerProviderFactory
   
    class=netsfehcachedistributionRMICacheManagerPeerProviderFactory
   
    properties=hostName=localhost
   
    port=
   
    socketTimeoutMillis=
   
    peerDiscovery=manual
   
    rmiUrls=//:/mobileCache|//:/mobileCache
   
    />
   
    <defaultCache maxElementsInMemory= eternal=false timeToIdleSeconds= timeToLiveSeconds= overflowToDisk=false/>
   
    <!
   
    配置自定義緩存
   
    maxElementsInMemory:緩存中允許創建的最大對象數
   
    eternal:緩存中對象是否為永久的如果是超時設置將被忽略對象從不過期
   
    timeToIdleSeconds:緩存數據空閒的最大時間也就是說如果有一個緩存有多久沒有被訪問就會被銷毀
   
    如果該值是 就意味著元素可以停頓無窮長的時間
   
    timeToLiveSeconds:緩存數據存活的時間緩存對象最大的的存活時間超過這個時間就會被銷毀
   
    這只能在元素不是永久駐留時有效如果該值是就意味著元素可以停頓無窮長的時間
   
    overflowToDisk:內存不足時是否啟用磁盤緩存
   
    memoryStoreEvictionPolicy:緩存滿了之後的淘汰算法
   
    每一個小時更新一次緩存(小時過期)
   
    >
   
    <cache name=mobileCache
   
    maxElementsInMemory=
   
    eternal=false
   
    overflowToDisk=true
   
    timeToIdleSeconds=
   
    timeToLiveSeconds=
   
    memoryStoreEvictionPolicy=LFU>
   
    <!
   
    RMI緩存分布同步查找 class使用netsfehcachedistributionRMICacheReplicatorFactory
   
    這個工廠支持以下屬性
   
    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
   
    asynchronousReplicationIntervalMillis=
   
    >
   
    <! 監聽RMI同步緩存對象配置 注冊相應的的緩存監聽類用於處理緩存事件如putremoveupdate和expire >
   
    <cacheEventListenerFactory
   
    class=netsfehcachedistributionRMICacheReplicatorFactory
   
    properties=replicateAsynchronously=true />
   
    replicatePuts=true
   
    replicateUpdates=true
   
    replicateUpdatesViaCopy=false
   
    replicateRemovals=true
   
    <! 用於在初始化緩存以及自動設置 >
   
    <bootstrapCacheLoaderFactory class=netsfehcachebootstrapBootstrapCacheLoaderFactory/>
   
    </cache></ehcache>自動發現
   
    自動發現配置和手動查找的方式有一點不同其他的地方都基本是一樣的同樣在ehcachexml中增加配置配置如下
   
    <!搜索某個網段上的緩存timeToLive
   
    是限制在同一個服務器
   
    是限制在同一個子網
   
    是限制在同一個網站
   
    是限制在同一個region
   
    是限制在同一個大洲
   
    是不限制><cacheManagerPeerProviderFactory
   
    class=netsfehcachedistributionRMICacheManagerPeerProviderFactory
   
    properties=peerDiscovery=automatic multicastGroupAddress=
   
    multicastGroupPort= timeToLive=/>


From:http://tw.wingwit.com/Article/program/Java/hx/201311/25706.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.