问题描述

在cache系统中writeThrough和writeBehind是两个常用的模式。

writeThrough是指,当用户更新缓存时,自动将值写入到数据源。

writeBehind是指,在用户更新缓存后异步更新到数据源。

ehcache实现

ehcache内部有一个CacheWriter接口,这个接口实现了cache一系列生命周期的钩子函数。

只需要实现自定义的写贯穿方法就可以在更新缓存时将对象写入底层的数据源

    //自定义的CacheWriter
public class MyCacheWriter implements CacheWriter {
public void write(Element element) throws CacheException {
System.out.println("write->"+element.getObjectValue()); //write到数据层
}
public void writeAll(Collection elements) throws CacheException {
System.out.println("writeall"); //write到数据层
}
...
}
//cacheWriter的工厂方法
public class MyCacheWriterFactory extends CacheWriterFactory{
@Override
public CacheWriter createCacheWriter(Ehcache cache, Properties properties) {
return new MyCacheWriter(); //返回自定义的CacheWriter
}

再将writer(的工厂方法)配置到cache中

    <cache name="writerCache" maxEntriesLocalHeap="10">
<cacheWriter writeMode="write-through" maxWriteDelay="8"
rateLimitPerSecond="5" writeCoalescing="true" writeBatching="true"
writeBatchSize="20" retryAttempts="2" retryAttemptDelaySeconds="2">
<cacheWriterFactory class="echach2.MyCacheWriterFactory"
properties="test=1;" propertySeparator=";" />
</cacheWriter>
</cache>

可以看到CacheWrite关于write有两个方法,write和writeall,这是通过配置中的writeMode控制的当配置为write-through时会在每一次更新缓存时同步调用write方法。而如果设置为write-behind时则会根据maxWriteDelay调用writeall来讲这段时间的数据调用writeall。

ehcahce的自动load机制

常规的cache使用方法是

    if(cache.exist("key")){
return cache.get("exist");
}else{
value=dao.get("key");
cache.put("key",value);
return value;
}

是在检测cache没有命中时从dao获得数据再跟新到缓存。

有以下两种办法可以减少这种复杂的编码

SelfPopulatingCache

在ehcache中有一套SelfPopulatingCache机制,它可以在缓存miss的情况下load底层数据

    //cache load工厂
public class MyCacheEntryFactory implements CacheEntryFactory {
public Object createEntry(Object key) throws Exception {
return new String("autoload "+key); //自定义load方法
}
}
//cache的装饰者工厂类
public class MyCacheDecoratorFactory extends CacheDecoratorFactory{
@Override
public Ehcache createDecoratedEhcache(Ehcache cache, Properties properties) {
return new SelfPopulatingCache(cache, new MyCacheEntryFactory());//使用SelfPopulatingCache并注册MyCacheEntryFactory
}

并在cache配置文件cache层中配置

    <cacheDecoratorFactory class="echach2.MyCacheDecoratorFactory"/>

这样获得的cache就会是经过装饰工厂生成的cache了

SelfPopulatingCache继承了BlockingCache,使用读写锁进行多线程更新和读取cache内容。

下面展示一下调用的代码

    @Test
public void readWriteThroughCache() throws InterruptedException {
CacheManager cache = CacheManager.create("cache.xml");
Ehcache readWriteCache = cache.addCacheIfAbsent("writerCache");
System.out.println("unexist key->"+readWriteCache.get(2).getObjectValue()); //自动读取值
readWriteCache.putWithWriter(new Element(1, "value")); //写贯穿a需调用putWithWriter
cache.shutdown();
}

输出为

    unexist key->autoload 2
write->value

使用getWithLoader

cache类拥有getWithLoader方法,它可以调用传入的loader对象进行数据load。但需要将get都改成这个方,而且对多线程同时写数据没有进行阻塞。

小结

以上介绍了ehcahe中write-thtough,write-behind与load-read的实现,可以在使用中适当选择数据加载及写入方式

ehcache2拾遗之write和load的更多相关文章

  1. ehcache2拾遗之cache持久化

    问题描述 应用在使用过程中会需要重启等,但是如果ehcache随着应用一起重启,那么刚重启的时候就会出现大量的miss,需要一定的访问量来重建缓存,如果缓存能够持久化,重启之后可以复用将会有助于缓解重 ...

  2. ehcache2拾遗之copyOnRead,copyOnWrite

    问题描述 缓存在提升应用性能,提高访问效率上都是至关重要的一步.ehcache也是广为使用的缓存之一.但是如果将一个可变的对象(如普通的POJO/List/Map等)存入缓存中,会导致怎样潜在的问题. ...

  3. Java 集合 HashMap & HashSet 拾遗

    Java 集合 HashMap & HashSet 拾遗 @author ixenos 摘要:HashMap内部结构分析 Java HashMap采用的是冲突链表方式 从上图容易看出,如果选择 ...

  4. java:Hibernate框架4(延迟加载(lazy),抓取(fetch),一级缓存,get,load,list,iterate,clear,evict,flush,二级缓存,注解,乐观锁和悲观锁,两者的比较)

    1.延时加载和抓取: hibernate.cfg.xml: <?xml version='1.0' encoding='UTF-8'?> <!DOCTYPE hibernate-co ...

  5. [C#.NET 拾遗补漏]08:强大的LINQ

    大家好,这是 [C#.NET 拾遗补漏] 系列的第 08 篇文章,今天讲 C# 强大的 LINQ 查询.LINQ 是我最喜欢的 C# 语言特性之一. LINQ 是 Language INtegrate ...

  6. load和initialize方法

      一.load 方法什么时候调用: 在main方法还没执行的时候 就会 加载所有类,调用所有类的load方法. load方法是线程安全的,它使用了锁,我们应该避免线程阻塞在load方法. 在项目中使 ...

  7. "NHibernate.Exceptions.GenericADOException: could not load an entity" 解决方案

     今天,测试一个项目的时候,抛出了这个莫名其妙的异常,然后就开始了一天的调试之旅... 花了很长时间,没有从代码找出任何问题... 那么到底哪里出问题呢? 根据下面那段长长的错误日志: -- ::, ...

  8. Redis命令拾遗二(散列类型)

    本文版权归博客园和作者吴双共同所有,欢迎转载,转载和爬虫请注明原文地址 :博客园蜗牛NoSql系列地址  http://www.cnblogs.com/tdws/tag/NoSql/ Redis命令拾 ...

  9. hibernate的get和load的区别

    在hibernate中我们知道如果要从数据库中得到一个对象,通常有两种方式,一种是通过session.get()方法,另一种就是通过session.load()方法,然后其实这两种方法在获得一个实体对 ...

随机推荐

  1. Hadoop streaming模式获取jobconf参数

    1. 像map_input_file这种环境变量是在hadoop-streaming.jar程序中设置的,所以无需-cmdenv map_input_file参数就可以在php中直接引用,如$var= ...

  2. C# "=="、Equals()、ReferenceEquals()区别

    对于值类型: ; ; 1.== 比较的是值内容 2.age2.Equals(age1) = false; Equals比较前需要转换成同类型,age1(int型)需显示转换成byte型 3.age1. ...

  3. NetBeans无法使用编码GBK安全地打开该文件(改为默认UTF-8)

    用文本编辑器打开NetBeans安装目录下etc\netbeans.conf文件,找到”netbeans_default_options=”字段,在后面添加” -J-Dfile.encoding=UT ...

  4. ArcGIS API中FindTask中文搜索无效,服务器编码问题URIEncoding="utf-8"

    问题来源:字符编码问题导致ArcMap中字符乱码或显示不正常,因而在F:\Program Files\ArcGIS\Server\framework\runtime\tomcat\conf中serve ...

  5. Tomcat settings should be set in Tomcat Preference Page解决

    选择tomcat version,然户找到该tomcat的主目录,输入在tomcat home,下面的参数会自动配置,点击apply. 然后在左边选择advanced,同样把tomcat的主目录复制在 ...

  6. (转)C# foreach 中获取索引index的方法

    在C# 开发中往往使用foreach 循环语句 来代替for循环语句.foreach 比 for 更加简洁高效.           foreach :                 foreach ...

  7. LintCode 463 Sort Integer

    这个是O(n2)的排序的总结 /* bubble sort */public static void sortIntegers(int[] A) { // Write your code here i ...

  8. Swift-ImageView响应点击事件

    随着Swift语言的不断更新迭代,纯Swift语言编写的代码更加紧凑简单,结合StoryBorad的使用,使开发苹果APP的门槛降低了不少.个人也是比较推荐使用Interface Builder去生成 ...

  9. ubuntu vps折腾记

    买了burgetVM的vps,512M内存/1024M交换内存,40G硬盘,2TB流量/月,cpu xeon E5-2620 操作系统选择了ubuntu 12,开始折腾. 第一步,配置vpn 找了很多 ...

  10. savepoint原理

    保存点 在MySQL中, 保存点SAVEPOINT属于事务控制处理部分.利用SAVEPOINT可以回滚指定部分事务,从而使事务处理更加灵活和精细.SAVEPOINT相关的SQL语句如下 SAVEPOI ...