EhCache 分布式下緩存對象的同步

jopen 12年前發布 | 64K 次閱讀 Ehcache 緩存組件

為了提升目前開發產品的性能,項目組內考慮將一些常用的數據放入緩存,并且今后要將系統分布式部署,以達到負載均衡的目的,因此緩存同步問題就不得不需要考慮,該項目中主要用EhCache產品,EhCache的優勢和劣勢這里就不做介紹,網上可以搜索,單從這次項目出發,說說他在項目中的應用,HibernateSpring都集成了EhCache,如果您的項目中用到這兩個框架,那將會大大降低開發復雜度,如果沒有使用此類框架,Ehcache還提供在項目中獨立使用。

先大概了解一下EhCache的原理吧,見下圖:

EhCache 分布式下緩存對象的同步

主要為三層,最上層的是CacheManager,它是操作Ehcache的入口。我們可以通過CacheManager.getInstance()(還有別的方法,可查看API)獲得一個單例的CacheManger;每個CacheManager都管理著多個Cache;而每個Cache都以Hash的方式,關聯著多個 ElementElement則是我們用于存放要緩存對象的地方。

先從EhCache在項目中獨立使用的Demo說起:

開發環境:Eclipse4.0(不受限制)、JDK1.5

引用Jar包:ehcache-core-2.5.2.jar

                   junit-3.8.1.jar

                  slf4j-api-1.6.1.jar

                  slf4j-jdk14-1.6.1.jar

新建一個Java Project,引入以上jar包,創建一個測試類TestPutElement,代碼如下:

package ehcache;

import java.net.URL;
import test.User;

import junit.framework.TestCase;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;

public class TestPutElement extends TestCase {

    public void testPut() throws Exception {

        URL url = TestPutCache.class.getClassLoader().getResource(
                "conf/ehcache.xml");
        CacheManager manager = new CacheManager(url);

        Cache cache = manager.getCache("metaCache");

        User user = new User();
        user.setName("張三");
        Element element = new Element("key",user);
        cache.put(element);

        manager.shutdown();
        System.out.println("已放入緩存!");
    }
}

創建一個POJO對象User,一定要經過序列化,并保證序列化UID的存在:

import java.io.Serializable;

public class User implements Serializable {

    private static final long serialVersionUID = -4402392412217726278L;
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

在ClassPath目錄下加入ehcache.xml文件,這也可以在Ehcachejar包中找到,有兩個注意事項,不要刪除defaultcache,如果是兩臺不同的電腦,那么把cacheManagerPeerProviderFactory中的第二個localhost換成另一臺機器IP即可,端口號是可以自定義的,不過要注意不要和系統使用的端口沖突,不然會報錯;

<?xml version="1.0" encoding="UTF-8"?>

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="ehcache.xsd"
         updateCheck="true" monitoring="autodetect"
         dynamicConfig="true">

    <diskStore path="java.io.tmpdir" />

    <!-- 指定除自身之外的網絡群體中其他提供同步的主機列表,用“|”分開不同的主機 -->
    <cacheManagerPeerProviderFactory
        class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
        properties="peerDiscovery=manual,rmiUrls=//localhost:40004/metaCache|//localhost:60000/metaCache" />

    <!-- 配宿主主機配置監聽程序,來發現其他主機發來的同步請求 -->
    <cacheManagerPeerListenerFactory
        class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
        properties="port=40004,socketTimeoutMillis=120000" />

    <!-- 默認緩存 -->
    <defaultCache maxElementsInMemory="10000" eternal="false"
        timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true"
        diskSpoolBufferSizeMB="30" maxElementsOnDisk="10000000"
        diskPersistent="false" diskExpiryThreadIntervalSeconds="120"
        memoryStoreEvictionPolicy="LRU">
    </defaultCache>

    <!-- 緩存 -->
    <cache name="metaCache" 
        maxElementsInMemory="1000" 
        eternal="false"
        timeToIdleSeconds="2000" 
        timeToLiveSeconds="1000" 
        overflowToDisk="false">
        <cacheEventListenerFactory
            class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" />
        <!-- <bootstrapCacheLoaderFactory
            class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
            properties="bootstrapAsynchronously=false" /> -->
    </cache>
</ehcache>

到此為止,放入緩存,也就是發送端配置好了,下面開始創建另個Java Project(),User類不變,必須要注意的是序列化UID和上一個Java Project要一致,否則會報ClassNotFound的錯誤,下面是測試類:

package ehcache;

import java.net.URL;

import test.User;
import junit.framework.TestCase;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;

public class TestGetCache extends TestCase {

    public void testGet() throws Exception {
        URL url = TestGetCache.class.getClassLoader().getResource(
                "conf/ehcache.xml");
        CacheManager manager = new CacheManager(url);

        Cache cache = manager.getCache("metaCache");

        while (true) {
            System.out.println("搜索中...");
            System.out.println("當前資源數:" + cache.getSize());
            Element element = cache.get("key");
            if (element != null) {
                User user = (User)element.getValue();
                System.out.println(user.getName());
                break;
            }
            Thread.sleep(1000);
        }
    }
}
ehcache.xml配置文件如下:

<?xml version="1.0" encoding="UTF-8"?>

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="ehcache.xsd"
         updateCheck="true" monitoring="autodetect"
         dynamicConfig="true">

    <diskStore path="java.io.tmpdir" />

    <!-- 指定除自身之外的網絡群體中其他提供同步的主機列表,用“|”分開不同的主機 -->
    <cacheManagerPeerProviderFactory
        class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
        properties="peerDiscovery=manual,rmiUrls=//localhost:40004/metaCache|//localhost:60000/metaCache" />

    <!-- 配宿主主機配置監聽程序,來發現其他主機發來的同步請求 -->
    <cacheManagerPeerListenerFactory
        class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
        properties="port=40004,socketTimeoutMillis=120000" />

    <!-- 默認緩存 -->
    <defaultCache maxElementsInMemory="10000" eternal="false"
        timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true"
        diskSpoolBufferSizeMB="30" maxElementsOnDisk="10000000"
        diskPersistent="false" diskExpiryThreadIntervalSeconds="120"
        memoryStoreEvictionPolicy="LRU">
    </defaultCache>

    <!-- 緩存 -->
    <cache name="metaCache" 
        maxElementsInMemory="1000" 
        eternal="false"
        timeToIdleSeconds="2000" 
        timeToLiveSeconds="1000" 
        overflowToDisk="false">
        <cacheEventListenerFactory
            class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" />
<!--         <bootstrapCacheLoaderFactory
            class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
            properties="bootstrapAsynchronously=true" /> -->
    </cache>
</ehcache>
下面就可以測試了,首先運行后一個java Project項目 ,然后運行前一個java Project,運行結果為:1,張三。

轉自:http://blog.csdn.net/stubbornpotatoes/article/details/7939672

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!