Java缓存Ehcache-Ehcache的Cache预热机制及代码实现(Cache Warming for multi-tier Caches)

Ehcache中Cache预热机制

Cache预热机制简介

Ehcache在程序启动的时候并不会立即去加载位于磁盘上的数据到内存,而是在数据被用到的时候去加载(lazy load)。因此在cache启动的时候,其内部没有数据。如果我们想在用到这些数据之前,它们全部被装载进内存,应该怎么做?

Ehcache提供了BootstrapCacheLoader机制来解决这个问题,在Cache被激活之前,它会得到运行。并且有两种模式:同步和异步。如果是同步模式,在CacheMana启动之前,加载便会完成;如果是异步模式,在CacheManager启动的时候,加载会在后台继续,而不是等到所需数据被需要的时候。

具体实现

我们只需要实现接口BootstrapCacheLoader定义自己的加载器MyBootstrapCacheLoader,继承BootstrapCacheLoaderFactory实现一个具体的加载工厂MyBootstrapCacheLoaderFactory即可实现数据的预热。

MyBootstrapCacheLoader负责实现怎么将数据加载进Cache,我们可以进行个性化的实现。MyBootstrapCacheLoaderFactory是一个具体的加载工厂,负责创建加载器实例,我们需要实现一些抽象方法。

下面看具体的代码实现(Java)。

MyBootstrapCacheLoader.java:

/**
 *
 * Copyright (c) 2004-2014 All Rights Reserved.
 */
package com..test.encache;

import java.util.List;

import net.sf.ehcache.CacheException;
import net.sf.ehcache.Ehcache;
import net.sf.ehcache.Element;
import net.sf.ehcache.bootstrap.BootstrapCacheLoader;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author
 * @version $Id: CustomBootstrapCacheLoader.java, v 0.1 2014年10月18日 上午10:57:26  Exp $
 */
public class MyBootstrapCacheLoader implements BootstrapCacheLoader {
    private static final Logger logger = LoggerFactory
                                           .getLogger(MyBootstrapCacheLoaderFactory.class);

    StatesDAO                   statesDAO;

    boolean                     asynchronous;

    /**
     * @see net.sf.ehcache.bootstrap.BootstrapCacheLoader#load(net.sf.ehcache.Ehcache)
     */
    public void load(Ehcache cache) throws CacheException {
        logger.info("load your cache with whatever you want....");

        List keys = cache.getKeys();
        for (int i = 0; i < keys.size(); i++) {
            logger.info("keys->" + keys.get(i));
        }

        try {
            List<String> dataList = getStatesDAO().findAllStates();
            cache.put(new Element(CacheConstants.KEY_ARRAY[0], dataList.get(0)));
            cache.put(new Element(CacheConstants.KEY_ARRAY[1], dataList.get(1)));

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        logger.info("load end....");
    }

    /**
     * @see net.sf.ehcache.bootstrap.BootstrapCacheLoader#isAsynchronous()
     */
    public boolean isAsynchronous() {
        return asynchronous;
    }

    /**
     * @see java.lang.Object#clone()
     */
    @Override
    public Object clone() throws CloneNotSupportedException {

        return super.clone();

    }

    public StatesDAO getStatesDAO() {
        return statesDAO;
    }

    public void setStatesDAO(StatesDAO statesDAO) {
        this.statesDAO = statesDAO;
    }

    /**
     * Setter method for property <tt>asynchronous</tt>.
     *
     * @param asynchronous value to be assigned to property asynchronous
     */
    public void setAsynchronous(boolean asynchronous) {
        this.asynchronous = asynchronous;
    }

}

MyBootstrapCacheLoaderFactory.java

/**
 *
 * Copyright (c) 2004-2014 All Rights Reserved.
 */
package com.test.encache;

import java.util.Properties;

import net.sf.ehcache.bootstrap.BootstrapCacheLoader;
import net.sf.ehcache.bootstrap.BootstrapCacheLoaderFactory;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * bootstrap cache loader
 *
 * @author
 * @version $Id: MyBootstrapCacheLoaderFactory.java, v 0.1 2014年10月17日 下午8:02:55  Exp $
 */
public class MyBootstrapCacheLoaderFactory extends BootstrapCacheLoaderFactory {
    private final String ASYNCHRONOUS_PROPERTY_KEY = "ASYNCHRONOUS";

    @Autowired
    private StatesDAO    statesDAO;

    public MyBootstrapCacheLoaderFactory() {
        super();
        // TODO Auto-generated constructor stub
    }

    private static final Logger logger = LoggerFactory
                                           .getLogger(MyBootstrapCacheLoaderFactory.class);

    @Override
    public BootstrapCacheLoader createBootstrapCacheLoader(Properties properties) {
        logger.info("MyBootstrapCacheLoaderFactory : create a BootstrapCacheLoader");
        MyBootstrapCacheLoader loader = new MyBootstrapCacheLoader();
        statesDAO = new StatesDAO();
        loader.setStatesDAO(statesDAO);
        loader.setAsynchronous(getAsyncFromProperty(properties));

        return loader;
    }

    private boolean getAsyncFromProperty(Properties properties) {
        String asynchronous = properties.getProperty(ASYNCHRONOUS_PROPERTY_KEY);

        return Boolean.valueOf(asynchronous);
    }
}

使用了Cache的读取磁盘数据的方法在StatesDAO类中,对此我们只是进行了模拟,从数据库中读取数据。

StatesDAO.java

/**
 *
 * Copyright (c) 2004-2014 All Rights Reserved.
 */
package com.test.encache;

import java.util.ArrayList;
import java.util.List;

import com.googlecode.ehcache.annotations.Cacheable;

/**
 *
 * @author
 * @version $Id: StatesDAO.java, v 0.1 2014年10月17日 下午8:07:05  Exp $
 */
public class StatesDAO {
    //annotation based caching and the name of cache should be defined in ehcache.xml. 

    @Cacheable(cacheName = "stateCache")
    public List<String> findAllStates() {
        List<String> dataList = new ArrayList<String>();

        //your call to database that returns a list of objects
        dataList.add("value1");
        dataList.add("value2");

        return dataList;
    }
}

Cache配置myehcache.xml:

<ehcache>

<diskStore path="D://localcache"/>

<cache
	name="stateCache"
	maxEntriesLocalHeap="10000"
	maxEntriesLocalDisk="1000"
	eternal="false"
	diskSpoolBufferSizeMB="20"
	timeToIdleSeconds="300"
	timeToLiveSeconds="600"
	memoryStoreEvictionPolicy="LFU"
	transactionalMode="off">
	<bootstrapCacheLoaderFactory class="com.test.encache.MyBootstrapCacheLoaderFactory"  properties="ASYNCHRONOUS=true"/>
</cache>

<cache
	name="stateCache2"
	maxEntriesLocalHeap="10000"
	maxEntriesLocalDisk="1000"
	eternal="false"
	diskSpoolBufferSizeMB="20"
	timeToIdleSeconds="300"
	timeToLiveSeconds="600"
	memoryStoreEvictionPolicy="LFU"
	transactionalMode="off">
	<bootstrapCacheLoaderFactory class="com.test.encache.MyBootstrapCacheLoaderFactory"  properties="ASYNCHRONOUS=false"/>
</cache>

</ehcache>

CacheManager配置ApplicationContext.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:ehcache="http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring
     http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring/ehcache-spring-1.1.xsd"
     default-autowire="byType">

	<ehcache:annotation-driven cache-manager="ehCacheManager" /> 

	<bean id="ehCacheManager"
		class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
		<property name="configLocation">
			<value>src/config/myehcache.xml</value>
		</property>
	</bean> 

</beans>

最后是测试代码:BootstrapCacheLoaderTest.java:

/**
 *
 * Copyright (c) 2004-2014 All Rights Reserved.
 */
package com.test.encache;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;

import org.apache.log4j.PropertyConfigurator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

/**
 *
 * @author
 * @version $Id: BootstrapCacheLoader.java, v 0.1 2014年10月18日 上午11:31:06 Exp $
 */
public class BootstrapCacheLoaderTest {
    private static String       log4jFileName      = "src/config/log4j.properties";
    private static String       xmlFileName        = "src/config/ApplicationContext.xml";
    private static String       ehcacheXmlFileName = "src/config/myehcache.xml";

    private static final Logger logger             = LoggerFactory
                                                       .getLogger(BootstrapCacheLoaderTest.class);

    private static CacheManager ehCacheManager;

    public static void main(String[] args) {
        configProperty();

        xmlLoad(ehcacheXmlFileName);

        String[] cacheNamesStrings = ehCacheManager.getCacheNames();
        logger.info("the number of caches in ehCacheManager : " + cacheNamesStrings.length);
        Cache cache = ehCacheManager.getCache(CacheConstants.CACHE_NAME1);
        Element element = cache.get(CacheConstants.KEY_ARRAY[0]);
        logger.info("the element of key  " + CacheConstants.KEY_ARRAY[0] + " is " + element);

    }

    /**
     * config properties
     *
     */
    private static void configProperty() {
        Properties properties = new Properties();
        FileInputStream istream;
        try {
            istream = new FileInputStream(log4jFileName);
            properties.load(istream);
            istream.close();
        } catch (FileNotFoundException e) {
            logger.error("File not found", e);
        } catch (IOException e) {
            logger.error("load file erroe", e);
        } finally {

        }

        //properties.setProperty("log4j.appender.file.File",logFile);
        PropertyConfigurator.configure(properties);
        logger.info("config properties success.");
    }

    private static void xmlLoad(String fileName) {
        ApplicationContext ctx = new FileSystemXmlApplicationContext(xmlFileName);

        ehCacheManager = (CacheManager) ctx.getBean("ehCacheManager");

    }
}

输出结果:

2014-10-18 15:17:45 INFO  BootstrapCacheLoaderTest:71 - config properties success.

2014-10-18 15:17:45 INFO  FileSystemXmlApplicationContext:513 - Refreshing org.[email protected]687b6889: startup date [Sat Oct 18 15:17:45 CST 2014]; root of context hierarchy

2014-10-18 15:17:45 INFO  XmlBeanDefinitionReader:316 - Loading XML bean definitions from file [D:\code\test\encache\src\config\ApplicationContext.xml]

2014-10-18 15:17:45 INFO  EhCacheManagerFactoryBean:136 - Initializing EhCache CacheManager

2014-10-18 15:17:46 INFO  MyBootstrapCacheLoaderFactory:38 - MyBootstrapCacheLoaderFactory : create a BootstrapCacheLoader

2014-10-18 15:17:46 INFO  MyBootstrapCacheLoaderFactory:38 - MyBootstrapCacheLoaderFactory : create a BootstrapCacheLoader

2014-10-18 15:17:46 INFO  MyBootstrapCacheLoaderFactory:34 - load your cache with whatever you want....

2014-10-18 15:17:46 INFO  MyBootstrapCacheLoaderFactory:51 - load end....

2014-10-18 15:17:46 INFO  MyBootstrapCacheLoaderFactory:34 - load your cache with whatever you want....

2014-10-18 15:17:46 INFO  MyBootstrapCacheLoaderFactory:51 - load end....

2014-10-18 15:17:46 INFO  BootstrapCacheLoaderTest:43 - the number of caches in ehCacheManager : 2

2014-10-18 15:17:46 INFO  BootstrapCacheLoaderTest:46 - the element of key  KEY1 is [ key = KEY1, value=value1, version=1, hitCount=1, CreationTime = 1413616666238, LastAccessTime = 1413616666302 ]

参考资料

Ehcache关于预热机制的官方文档

Load EhCache diskstore content into memory

How to load data to Ehcache when the application starts

时间: 2024-10-03 04:53:32

Java缓存Ehcache-Ehcache的Cache预热机制及代码实现(Cache Warming for multi-tier Caches)的相关文章

Java缓存组件 EhCache 入门教程

1.技术背景: 系统缓存是位于应用程序与物理数据源之间,用于临时存放复制数据的内存区域,目的是为减少应用程序对物理数据源访问的次数,从而提高应用程序的运行性能.缓存设想内存是有限的,缓存的时效性也是有限的,所以可以设定内存数量的大小可以执行失效算法,可以在内存满了的情况下,按照最少访问等算法将缓存直接移除或切换到硬盘上. Ehcache从Hibernate发展而来,逐渐涵盖了Cache界的全部功能,是目前发展势头最好的一个项目,具有快速.简单.低消耗.扩展性强.支持对象或序列化缓存,支持缓存或元

Java的进程内缓存框架:EhCache (转)

EhCache 是一个纯Java的进程内缓存框架,具有快速.精干等特点,是Hibernate中默认的CacheProvider. Ehcache缓存的特点: 1. 快速. 2. 简单. 3. 多种缓存策略 4. 缓存数据有两级:内存和磁盘,因此无需担心容量问题 5. 缓存数据会在虚拟机重启的过程中写入磁盘 6. 可以通过RMI.可插入API等方式进行分布式缓存 7. 具有缓存和缓存管理器的侦听接口 8. 支持多缓存管理器实例,以及一个实例的多个缓存区域 9. 提供Hibernate的缓存实现 E

Java的进程内缓存框架:EhCache

Ehcache缓存的特点: 1. 快速. 2. 简单. 3. 多种缓存策略 4. 缓存数据有两级:内存和磁盘,因此无需担心容量问题 5. 缓存数据会在虚拟机重启的过程中写入磁盘 6. 可以通过RMI.可插入API等方式进行分布式缓存 7. 具有缓存和缓存管理器的侦听接口 8. 支持多缓存管理器实例,以及一个实例的多个缓存区域 9. 提供Hibernate的缓存实现 Ehcache缓存的使用(1) – 安装ehcache Ehcache 的特点,是一个纯Java ,过程中(也可以理解成插入式)缓存

Java 开源分布式缓存框架Ehcache

Ehcache 是一个Java实现的开源分布式缓存框架,EhCache 可以有效地减轻数据库的负载,可以让数据保存在不同服务器的内存中,在需要数据的时候可以快速存取.同时EhCache 扩展非常简单,官方提供的Cache配置方式有好几种.你可以通过声明配置.在xml中配置.在程序里配置或者调用构造方法时传入不同的参数. 以下是EhCache 的架构图: Ehcache有以下特点: 存取速度非常快,性能很不错. 可以应用多种缓存策略. 分级缓存,用户可以指定哪些数据在硬盘中缓存,哪些数据在内存中缓

Java 缓存技术之 ehcache

1. EHCache 的特点,是一个纯Java ,过程中(也可以理解成插入式)缓存实现,单独安装Ehcache ,需把ehcache-X.X.jar 和相关类库方到classpath中.如项目已安装了Hibernate ,则不需要做什么..直接可以使用Ehcache Cache 存储方式 :内存或磁盘 2. 单独使用 EHCache 所以大概步骤为: 第一步:生成CacheManager对象 第二步:生成Cache对象 第三步:向Cache对象里添加由key,value组成的键值对的Elemen

java缓存(3、Oscache和Ehcache)

概述 oscache和ehcache都是进程级缓存,本篇讲解这两个框架的功能和区别. oscache oscache现在已经不再维护,但任可以下载使用,它可以缓存页面,可以实现整个页面的缓存,也可以实现页面其可以缓存数据对象,对于页面的缓存,我们需要注意:同一个浏览器,访问同一个页面多次时,会只访问一次业务逻辑层,不同浏览器,访问同一个页面多次时,每个浏览器会分别访问一次业务逻辑层.oscache缓存,可实现持久化功能. Demo下载 ehcache ehcache框架使用的相对来说,比较广泛,

Hibernate二级缓存以及ehcache的搭建配置

前言 这次主要复习Hibernate的二级缓存的相关知识,配置以及使用.二级缓存主要采用第三方的ehcache,也将介绍ehcache缓存的相关配置属性以及在项目中的搭建,具体的项目查看下一篇的 Maven搭建SpringMVC+Hibernate项目详解 的文章.(之前使用过Hibernate的二级缓存,但是没自己搭建和研究过,现在花了半天时间搭建了一下,写下来供大家参考) 1.Hibernate二级缓存 Hibernate包括两个级别的缓存: 1.一级缓存:默认总是启用的session级别的

初识缓存以及ehcache初体验

1.缓存的意义 缓存机制就是将数据库中常用的数据取出放入内存中,程序调用时直接从内存中取,丌用每次使用  数据都访问数据库,这样提高了效率. 2.缓存需要关注的问题 1)  缓存的更新 缓存中的数据必须是同数据库中数据保持一致. 2)  缓存的命中率 提高缓存数据的利用率,缓存中存放的是用户常用的数据,如果缓存中存放的是用户丌常用的, 那么就说缓存的命中率丌高. 有些时候,是某些缓存数据在某个时刻使用率高,某个时刻使用率低,所以需要时刻更新, 以提高缓存命中率. Hibernate的缓存机制 ?

缓存插件 EHCache

EHCache是来自sourceforge(http://ehcache.sourceforge.net/)的开源项目,也是纯Java实现的简单.快速的Cache组件. 下载jar包 Ehcache 对象.数据缓存:http://ehcache.org/downloads/destination?name=ehcache-core-2.5.2-distribution.tar.gz&bucket=tcdistributions&file=ehcache-core-2.5.2-distrib