问题描述

在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. Unity3d Android Http 开发中的坑(吐槽

    在一般的U3D网络开发中,直接使用WWW类便足够正常使用,但我在发现使用WWW下载大文件时,会导致整个程序卡顿的情况(不清楚是否我个人电脑问题),所以干脆使用HttpWebRequest/HttpWe ...

  2. 【Java】使用iText生成PDF文件

    iText介绍 iText是著名的开放源码的站点sourceforge一个项目,是用于生成PDF文档的一个java类库.通过iText不仅可以生成PDF或rtf的文档,而且可以将XML.Html文件转 ...

  3. Unity 编辑器的 界面布局 保存方法

    在软件界面的右上角(关闭按钮的下方),点击  layout  (界面)的下拉箭头. 弹出选项中的 save layout....(保存界面选项),输入命名,就可以生成这个界面的布局.  (软件本身也有 ...

  4. MVC文件上传文件限制

    最近想实现MVC中文件上传限制,总觉得有便利的方法,找了半天就找到加属性accept <input type="file" id="file" name= ...

  5. <转>浅析长度为0的数组

    前面在看Xen的源码时,遇到了一段代码,如下所示: 注意上面最后一行的代码,这里定义了一个长度为的数组,这种用法可以吗?为什么可以使用长度为0 的数组?长度为的数组到底怎么使用?……这篇文章主要针对该 ...

  6. 读取全球ip获取用户地区

    这个 首先说明下.ip库是qq纯真ip库 dat文件类型 public static string QQipPath = AppDomain.CurrentDomain.BaseDirectory + ...

  7. 用栈解决Largest Rectangle问题

    一问题描述 Given n non-negative integers representing the histogram's bar height where the width of each ...

  8. win7下matplotlib安装(64位)

    前段时间爬了一些数据,想着以后要将数据的分析结果什么的展示出来,就想着下个MATLAB,某天在微信上的一篇文章发现matplotlib库,是用于Python的一个不错的图形化库,就想着装上耍耍.不过安 ...

  9. Devexpress 汉化

    DevExpress是一个比较有名的界面控件套件,提供了一系列的界面控件套件的DotNet界面控件.对于较老的版本(例如之前项目中遇到的dev9),对于汉化(应该说本地化Localization)支持 ...

  10. Activity设置全屏的三种方法

    1.super.onCreate(savedInstanceState)方法之前调用:            setTheme(android.R.style.Theme_Light_NoTitleB ...