问题描述

在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. linux系统编程之I/O内核数据结构

    文件在内核中是用三种数据结构进行表示的 (1)文件描述符表:文件描述符表是一个结构体数组,数组的下标就是open函数返回的文件描述符. 文件描述符表的每一个记录有两个字段   *文件描述符标志 * 文 ...

  2. .net 批量打印可实现方案

    最近几年一直在教育行业工作,主要负责竞赛类系统的开发工作,包括网上报名,安排考场,在线考试,学业报告书等. 打印功能在这个信息化时代非常普遍,浏览器都自带打印功能,通常的做法是调用 window.pr ...

  3. Java String字符串方法

    1.String构造函数 1> String() 2> String(char[] chars) String(char[] chars,int startIndex,int numCha ...

  4. javascript code snippet -- 保留小数点位数

    js1.5以上可以利用toFixed(x) ,可指定数字截取小数点后 x位 for example : //round "original" to two decimals var ...

  5. javaWeb实现文件上传与下载 (转)

    文件上传概述 实现web开发中的文件上传功能,需完成如下二步操作: 在web页面中添加上传输入项 在servlet中读取上传文件的数据,并保存到本地硬盘中. 如何在web页面中添加上传输入项? < ...

  6. 【线段树】bzoj1018 [SHOI2008]堵塞的交通traffic

    线段树的每个叶子节点存一列. 每个节点维护六个域,分别是左上左下.左上右上.左上右下.左下右上.左下右下.右上右下在区间内部的连通性,不考虑绕出去的情况. 初始每个叶子的左上左下.右上右下是连通的. ...

  7. 20151013 C# 第一篇 流程控制语句

    20151013 流程控制语句: 1.选择语句 if … else if...else 选择语句 if(布尔表达式){  语句块:} if(布尔表达式){  语句块1:}else{  语句块2:} i ...

  8. React Native填坑之旅--布局篇

    代码在这里: https://github.com/future-challenger/petshop/tree/master/client/petshop/src/controller 回头看看RN ...

  9. webapi版本升级管理

    由于近期公司人员流动,本人临时客串webapi开发,针对开发过程中碰到一些问题做一些改进 1.当前做法 项目webapi项目是居于asp.net框架开发的,每个功能模块新建一个api控制器,比如Use ...

  10. php 用户ip的获取

    $_SERVER 这个变量我很喜欢,里面有很多服务器和用户的配置.资料.特别是在获取用户ip 的时候 直接$_SERVER['REMOTE_ADDR'] 就可以或许,但这是没有使用 反向代理服务器的情 ...