从名字上来看JBoss Cache很容易使人联想到JBoss Web服务器,但是实际上,你可以“认为”他们之间没有任何关系,学习使用JBoss Cache时不需要你对JBoss Web服务器有任何了解。
什么是JBoss Cache
就像它的名字所显示的那样,它是一种缓存。它被设计用来缓存那些经常被访问的Java对象,这样就可以明显的提高系统的性能,可以很轻松的解决掉数据访问的瓶颈,比如连接数据库等。
JBoss Cache是一种复制缓存,它可以自动与集群中的其他服务器同步状态,这样就可以保证在其中一台或者几台服务器突然挂掉之后恢复缓存,具有很高的可靠性能。
JBoss Cache存储结构为树状结构,使用Fqn(Full Qualified Name)唯一定位其中一个Node,如下图,其中每个方框代表一个独立的JVM。
以上只简单的介绍JBoss Cache的概念,详细信息请参考官方文档: http://jboss.org/jbosscache
既然cache是存在内存中的,那就需要应对各种突发性的事件,以保证它的高可靠性,比如内存不足,或者服务器宕机等,为了解决此类问题,JBoss Cache引入了CacheLoader的概念去备份内存中的缓存数据,同时为了提高系统的性能,CacheLoader可以被配置用来在系统启动的时候预加载部分或者全部历史缓存。
JBoss Cache附带了多种CacheLoader的默认实现,包括FileCacheLoader, JDBCCacheLoader, S3CacheLoader, TCPDelegatingCacheLoader, TransformingCacheLoader等,从名字可以很容理解每种CacheLoader的应用场景,本文将主要演示FileCacheLoader。
简单概括一下什么是CacheLoader
JBoss Cache可以通过CacheLoader将内存中的缓存备份到datastore中。如果JBoss Cache配置了CacheLoader,那么JBoss Cache将提供以下功能:
1. 当访问某个缓存元素的时候, 如果该元素不在内存中,比如它可能被钝化或者因为服务器重启了,那么CacheLoader就会自动的在datastore中查询该元素,如果存在,将会加载到内存中。
2. 当某个缓存元素被修改,添加或者删除的时候,CacheLoader会将这种变化持久化到datastore中。如果使用了事务,那会以事务为单位持久化这种变化。
好了,闲话不在多说了,详情可以参考官方的用户手册:http://docs.jboss.org/jbosscache/3.2.1.GA/userguide_en/html_single/index.html#d0e2507
下面将演示一下如果设置使用FileCacheLoader
首先创建一个FileCache类封装JBoss Cache的相关操作,如下:
package com.javaeye.terrencexu.jbosscache; import java.io.File; import java.util.Map; import org.jboss.cache.Cache; import org.jboss.cache.DefaultCacheFactory; import org.jboss.cache.Fqn; import org.jboss.cache.Node; import org.jboss.cache.config.CacheLoaderConfig; import org.jboss.cache.config.Configuration; import org.jboss.cache.loader.FileCacheLoader; import org.jboss.cache.loader.FileCacheLoaderConfig; /** * <p> * This is demo to illustrate how to use the JBoss Cache to cache your * frequently accessed Java objects in order to dramatically improve * the performance of your applications. This makes it easy to remove * data access bottlenecks, such as connecting to a database. * </p> * <p> * As a rule of thumb, it is recommended that the FileCacheLoader not * be used in a highly concurrent, transactional or stressful environment, * ant its use is restricted to testing. * </p> * * @author TerrenceX * * @param <T> */ public class FileCache<T> { /** * The JBoss Cache, used to cache frequently accessed Java objects. */ private Cache<String, T> cache; /** * @constructor * @param fsCacheLoaderLocation The file system location to store the cache */ public FileCache(File fsCacheLoaderLocation) { cache = initCache(fsCacheLoaderLocation); } /** * Create a Cache and whose cache loader type is File Cache Loader * * @param fsCacheLoaderLocation The file position used to store the cache. * * @return Cache */ public Cache<String, T> initCache(File fsCacheLoaderLocation) { // initiate a FileCacheLoader instance FileCacheLoader fsCacheLoader = new FileCacheLoader(); // prepare the file cache loader configuration file for File Cache Loader FileCacheLoaderConfig fsCacheLoaderConfig = new FileCacheLoaderConfig(); fsCacheLoaderConfig.setLocation(fsCacheLoaderLocation.toString()); fsCacheLoaderConfig.setCacheLoader(fsCacheLoader); // set configuration to File Cache Loader fsCacheLoader.setConfig(fsCacheLoaderConfig); // prepare the configuration for Cache Configuration config = new Configuration(); config.setCacheLoaderConfig(new CacheLoaderConfig()); config.getCacheLoaderConfig().addIndividualCacheLoaderConfig(fsCacheLoaderConfig); // create a Cache through the default cache factory return new DefaultCacheFactory<String, T>().createCache(config); } /** * Add a new node into the tree-node hierarchy * * @param fqn Full Qualified Name for the new node * @return */ public Node<String, T> addNode(Fqn<String> fqn) { return cache.getRoot().addChild(fqn); } /** * Remove a specified node from the tree-node hierarchy * * @param fqn Full Qualified Name for the specified node */ public void removeNode(Fqn<String> fqn) { cache.removeNode(fqn); } /** * Add node information to the specified node. * * @param fqn Full Qualified Name for the specified node * @param key The key of the node information * @param value The value of the node information */ public void addNodeInfo(Fqn<String> fqn, String key, T value) { cache.put(fqn, key, value); } /** * Batch add node information to the specified node. * * @param fqn Full Qualified Name for the specified node * @param infos Node informations map */ public void addNodeInfos(Fqn<String> fqn, Map<String, T> infos) { cache.put(fqn, infos); } /** * Get node information from the specified node. * * @param fqn Full Qualified Name for the specified node * @param key The key of the node information * @return */ public T getNodeInfo(Fqn<String> fqn, String key) { return cache.get(fqn, key); } /** * Remove node information from the specified node. * * @param fqn Full Qualified Name for the specified node * @param key The key of the node information */ public void removeNodeInfo(Fqn<String> fqn, String key) { cache.remove(fqn, key); } }
下面是一个测试的例子:
package com.javaeye.terrencexu.jbosscache; import java.io.File; import org.jboss.cache.Fqn; public class Main { public static void main(String[] args) { FileCache<String> fileCache = new FileCache<String>(new File("d:\\tmp")); Fqn<String> jimmyFqn = Fqn.fromString("/com/manager/jimmy"); Fqn<String> hansonFqn = Fqn.fromString("/com/developer/hanson"); fileCache.addNode(jimmyFqn); fileCache.addNode(hansonFqn); fileCache.addNodeInfo(jimmyFqn, "en-name", "Jimmy Zhang"); fileCache.addNodeInfo(jimmyFqn, "zh-name", "Zhang Ji"); fileCache.addNodeInfo(hansonFqn, "en-name", "Hanson Yang"); fileCache.addNodeInfo(hansonFqn, "zh-name", "Yang Kuo"); String enName = fileCache.getNodeInfo(hansonFqn, "en-name"); System.out.println(enName); } }
运行结果如下:
- JBossCache MBeans were successfully registered to the platform mbean server. - JBoss Cache version: JBossCache 'Malagueta' 3.2.5.GA Hanson Yang
生成的缓存文件目录结构如下:
D:/tmp/com.fdb/manage.fdb/jimmy.fdb/data.dat
D:/tmp/com.fdb/developer.fdb/hanson.fdb/data.dat
本文仅仅是通过FileCacheLoader演示如何使用JBoss Cache,在真正的集群环境中建议不要使用FileCacheLoader, 它只是用来测试玩玩儿而已。
-- done --