当前访客身份:游客 [ 登录  | 注册加入尚学堂]
启用新域名sxt.cn
新闻资讯

EhCache 分布式缓存对象的同步

helloworld 发表于 2年前  | 评论(0 )| 阅读次数(591 )|   0 人收藏此文章,   我要收藏
摘要 为了提升目前开发产品的性能,项目组内考虑将一些常用的数据放入缓存,并且今后要将系统分布式部署,以达到负载均衡的目的,因此缓存同步问题就不得不需要考虑,该项目中主要用EhCache产品,EhCache的优势和劣势这里就不做介绍,网上可以搜索,单从这次项目出发,说说他在项目中的应用,Hibernate和Spring都集成了EhCache,如果您的项目中用到这两个框架,那将会大大降低开

为了提升目前开发产品的性能,项目组内考虑将一些常用的数据放入缓存,并且今后要将系统分布式部署,以达到负载均衡的目的,因此缓存同步问题就不得不需要考虑,该项目中主要用EhCache产品,EhCache的优势和劣势这里就不做介绍,网上可以搜索,单从这次项目出发,说说他在项目中的应用,HibernateSpring都集成了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,张三。
分享到:0
关注微信,跟着我们扩展技术视野。每天推送IT新技术文章,每周聚焦一门新技术。微信二维码如下:
微信公众账号:尚学堂(微信号:bjsxt-java)
声明:博客文章版权属于原创作者,受法律保护。如果侵犯了您的权利,请联系管理员,我们将及时删除!
(邮箱:webmaster#sxt.cn(#换为@))
北京总部地址:北京市海淀区西三旗桥东建材城西路85号神州科技园B座三层尚学堂 咨询电话:400-009-1906 010-56233821
Copyright 2007-2015 北京尚学堂科技有限公司 京ICP备13018289号-1 京公网安备11010802015183