ehcache是一个开源的Java本地缓存框架,同时以replication的形式提供分布式缓存管理。这里介绍下使用RMI手动配置的方法在一个JVM里面启动多个CacheManager来实现分布式缓存。
这里配置3个CacheManager,由于只有一台机器,所以实在一个JVM里面使用3个CacheManager的方法来模拟分布式。
<?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" name="nodeA">
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=manual,
rmiUrls=//localhost:40002/cache1|//localhost:40003/cache1" />
<cacheManagerPeerListenerFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
properties="hostName=localhost, port=40001,
socketTimeoutMillis=2000" />
<cache name="cache1" maxEntriesLocalHeap="10" eternal="false"
timeToIdleSeconds="100" timeToLiveSeconds="100" overflowToDisk="false">
<cacheEventListenerFactory
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
properties="replicateAsynchronously=true, replicatePuts=true, replicateUpdates=true,
replicateUpdatesViaCopy=false, replicateRemovals=true " />
</cache>
</ehcache>
<?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" name="nodeB">
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=manual,
rmiUrls=//localhost:40001/cache1|//localhost:40003/cache1" />
<cacheManagerPeerListenerFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
properties="hostName=localhost, port=40002,
socketTimeoutMillis=2000" />
<cache name="cache1" maxEntriesLocalHeap="10" eternal="false"
timeToIdleSeconds="100" timeToLiveSeconds="100" overflowToDisk="false">
<cacheEventListenerFactory
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
properties="replicateAsynchronously=true, replicatePuts=true, replicateUpdates=true,
replicateUpdatesViaCopy=false, replicateRemovals=true " />
</cache>
</ehcache>
<?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" name="nodeC">
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=manual,
rmiUrls=//localhost:40001/cache1|//localhost:40002/cache1" />
<cacheManagerPeerListenerFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
properties="hostName=localhost, port=40003,
socketTimeoutMillis=2000" />
<cache name="cache1" maxEntriesLocalHeap="10" eternal="false"
timeToIdleSeconds="100" timeToLiveSeconds="100" overflowToDisk="false">
<cacheEventListenerFactory
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
properties="replicateAsynchronously=true, replicatePuts=true, replicateUpdates=true,
replicateUpdatesViaCopy=false, replicateRemovals=true " />
</cache>
</ehcache>
package com.suifengfei.learn.ehcachelearn.replication;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RmiReplication {
private final static Logger logger = LoggerFactory.getLogger(RmiReplication.class);
private CacheManager nodeA ;
private CacheManager nodeB ;
private CacheManager nodeC ;
public void setup(){
nodeA = CacheManager.newInstance("src/main/resources/ehcache-rmi-replication-nodeA.xml");
nodeB = CacheManager.newInstance("src/main/resources/ehcache-rmi-replication-nodeB.xml");
nodeC = CacheManager.newInstance("src/main/resources/ehcache-rmi-replication-nodeC.xml");
}
public void shutdown(){
if( null != nodeA ){
nodeA.shutdown();
}
if( null != nodeB ){
nodeB.shutdown();
}
if( null != nodeC ){
nodeC.shutdown();
}
}
public static void main(String[] args) {
RmiReplication rmiReplication = new RmiReplication();
rmiReplication.setup();
try {
rmiReplication.simpleTest();
} catch (InterruptedException e) {
e.printStackTrace();
}
rmiReplication.shutdown();
}
private void simpleTest() throws InterruptedException{
Cache cacheA1 = nodeA.getCache("cache1");
Cache cacheB1 = nodeB.getCache("cache1");
Cache cacheC1 = nodeC.getCache("cache1");
Element e1 = new Element("a", "hello") ;
cacheA1.put(e1);
Thread.sleep(2000);
Element e1_B = cacheB1.get("a");
if( null != e1_B ){
String e1V = (String)e1_B.getValue();
logger.info("e1 value from nodeB:" + e1V);
}
Element e1_C = cacheC1.get("a");
if( null != e1_C ){
String e1V = (String)e1_C.getValue();
logger.info("e1 value from nodeC:" + e1V);
}
}
}
[22 13:02:48,411 INFO ] [main] replication.RmiReplication - e1 value from nodeB:hello
[22 13:02:48,411 INFO ] [main] replication.RmiReplication - e1 value from nodeC:hello
在配置ehcache的时候,有一点需要注意,需要配置好ehcache元素的name属性,虽然这个属性是一个optinal的,我们看一下官方文档
CacheManager.newInstance(Configuration configuration) – Create a new CacheManager or return the existing one named in the configuration.
也就说每一个CacheManager都有一个name,如果不配置name属性的话,这个name会是一个相同的默认值,在测试代码中虽然nodeA,nodeB,nodeC加载了3个不同的配置,但是由于name都是相同的,返回的nodeB和nodeC其实和nodeA引用了相同的对象,在运行到缓存操作的时候,由于调用不到对方的RMI接口服务,会报错。
[22 13:08:44,148 DEBUG] [Replication Thread] distribution.ManualRMICacheManagerPeerProvider - Looking up rmiUrl //localhost:40002/cache1 through exception Connection refused to host: localhost; nested exception is:
java.net.ConnectException: Connection refused: connect. This may be normal if a node has gone offline. Or it may indicate network connectivity difficulties
java.rmi.ConnectException: Connection refused to host: localhost; nested exception is:
java.net.ConnectException: Connection refused: connect
通过下面的CachaManager的实现也可以看出来对于这个name的判断
private static CacheManager newInstance(Configuration configuration, String msg) throws CacheException {
synchronized (CacheManager.class) {
String name = configuration.getName();
if (name == null) {
name = DEFAULT_NAME;
}
CacheManager cacheManager = CACHE_MANAGERS_MAP.get(name);
if (cacheManager == null) {
LOG.debug(msg);
cacheManager = new CacheManager(configuration);
}
return cacheManager;
}
}
分享到:
相关推荐
介绍ehcache做jvm缓存,ehcache做分布式缓存,redis做分布式缓存,redis分片集群,redis哨兵,redis基本数据,redis主从复制,redis和ehcache的二级缓存,redis雪崩效应,redis缓存穿透(整个环境搭建基于Centos,代码...
JAVA 面经--JVM,spring框架,分布式,数据库
akka, 在JVM上,构建高度并发分布式和弹性消息驱动的应用 Akka我们相信编写正确的并发&分布式。弹性和弹性应用程序太难。 大多数时候,因为我们使用了错误的工具和错误的抽象级别。Akka是来改变。利用角色模型提升...
学习总结 包括Java JVM MySQL NoSQL UML 缓存 消息 分布式事务-StudySummary
学习总结 包括Java JVM MySQL NoSQL UML 缓存 消息 分布式事务 SOA 微服务 敏捷 架构设
学习关于JVM基础,java内模型的全面透析,Jar hell问题以及解决办法,Class文件格式 • Java编译执行流程 • ClassFile的格式介绍 • ClassFile中FieldInfo和MethodInfo介绍 • 类型描述Descriptor介绍 • ClassFile...
12 分布式框架专题-分布式缓存技术Redis 13 分布式框架专题-分布式缓存技术Redis 14 分布式框架专题-分布式技术MongoDBSharding-Sphere 15 分布式框架专题-分布式通信Netty框架 16 分布式框架专题-分布式技术...
2017年最新的关于jvm的书,里面还包含了如何编译openjdk部分,值得一看。
HazelCastClient:这个类是一个客户端应用程序的例子,它连接到分布式缓存并检查状态,如果它已经启动,它将打印以下消息。 “我没有启动,节点ID-'1'的主节点'Node1'已经启动..” 要运行此工具: 可以使用 git ...
分布式锁是在分布式环境下(多个JVM进程)控制多个客户端对某一资源的同步访问的一种实现,与之相对应的是线程锁,线程锁控制的是同一个JVM进程内多个线程之间的同步。分布式锁的一般实现方法是在应用服务器之外通过...
有Ehcache 3.x、MapDB实现分布式缓存 进程内缓存和磁盘缓存,在多JVM实例的情况下,会存在两个问题: 1、单机容量问题; 2、数据一致性问题(多台JVM实例的缓存数据不一致怎么办?),这个问题不用纠结, 既然数据...
jcache-samples 其中包含用于Java分布式Java缓存的Java Colombo Meetup的示例。 [1]这演示了将Javax JCache与Hazelcast用作缓存服务器。... cache-setter-创建一个缓存,并向其中添加一组对象。 cache-getter
java基础,JVM,消息中间件,分布式缓存,MySQL数据库,等等相关面试题
其一是标准参数(-),所有的JVM实现都必须实现这些参数的功能,而且向后兼容; 其二是非标准参数(-X),默认jvm实现这些参数的功能,但是并不保证所有jvm实现都满足,且不保证向后兼容; 其三是非Stable参数(-XX...
JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。 引入Java语言虚拟机后,Java语言在不同平台...
java对象在jvm中的存储情况 jvm
从源码角度解读HotSpot的内部实现机制,本书主要包含三大部分——JVM数据结构设计与实现、执行引擎机制及内存分配模型
NeatJVM,java中的jvm实现.zip