您的位置:首页 > 其它

常用缓存框架比较

2017-02-27 10:31 316 查看
研究缓存框架的话,研究一下ehcache肯定是不会错的,一般来说其特性和值得研究的方向就是以下几点:

1. 快速

2. 简单

3. 多种缓存策略

4. 缓存数据有两级:内存和磁盘,因此无需担心容量问题

5. 缓存数据会在虚拟机重启的过程中写入磁盘

6. 可以通过RMI、可插入API等方式进行分布式缓存

7. 具有缓存和缓存管理器的侦听接口

8. 支持多缓存管理器实例,以及一个实例的多个缓存区域

如果自己开发相同的缓存框架的话,注意以上几点肯定是错不了的,在另外一方面来说,不只是要注意以上这些。

还需要注意缓存框架所占的内存大小,在设计与实现时最大的内存使用值,因为当缓存框架过大时,会出现缓存框架和应用程序抢占内存的情况,所以不建议缓存框架能够缓存太多的东西,在此可以和redis或者是memcached结合在一起来使用,研究ehcache相关特性后,将自己做的缓存框架当做一级缓存,redis作为二级缓存,redis进行应队列发布订阅,然后相应应用程序监听队列,随之更新自己研发的缓存框架。这些都是需要考虑的。

redis是个nosql db

 Ehcache有以下特点:
存取速度非常快,性能很不错。
可以应用多种缓存策略。
分级缓存,用户可以指定哪些数据在硬盘中缓存,哪些数据在内存中缓存。
可以通过RMI、可插入API等方式进行分布式缓存。
具有缓存和缓存管理器的侦听接口。
支持多缓存管理器实例,以及一个实例的多个缓存区域。
默认提供Hibernate的缓存实现。

  Ehcache的配置示例代码:
<ehcache>
<diskStore path=”java.io.tmpdir”/>
<defaultCache
maxElementsInMemory=”10000″
eternal=”false”
timeToIdleSeconds=”120″
timeToLiveSeconds=”120″
overflowToDisk=”true”
maxElementsOnDisk=”10000000″
diskPersistent=”false”
diskExpiryThreadIntervalSeconds=”120″
memoryStoreEvictionPolicy=”LRU”
/>
</ehcache>


  在同类的Java缓存框架中,Ehcache配置相对简单,也比较容易上手,最大的优势是它支持分布式缓存

  Cacheonix的特点
可靠的分布式 Java 缓存
通过复制实现高可用性
支持泛型的缓存 API
可与 ORM 框架集成
使用数据分区实现负载均衡
支持非多播网络
高性能计算
快速的本地 Java 缓存
分布式锁机制

  Cacheonix的架构图



  Cacheonix分布式缓存XML配置
<?xml version ="1.0"?>
<cacheonix xmlns="http://www.cacheonix.com/schema/configuration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.cacheonix.com/schema/configuration http://www.cacheonix.com/schema/cacheonix-config-2.0.xsd"> 
<server>

<listener>
<tcp port="8879" buffer="128k"/>
</listener>

<broadcast>
<multicast multicastAddress="225.0.1.2" multicastPort="9998" multicastTTL="0"/>
</broadcast>

<partitionedCache name="customer.cache">
<store>
<lru maxElements="10000" maxBytes="10mb"/>
<expiration idleTime="120s"/>
</store>
</partitionedCache>

<partitionedCache name="invoice.cache">
<store>
<lru maxElements="10000" maxBytes="10mb"/>
<expiration idleTime="120s"/>
</store>
</partitionedCache>

<partitionedCache name="search.results.cache">
<store>
<lru maxBytes="5mb"/>
</store>
</partitionedCache>
</server>
</cacheonix>


  Cacheonix缓存的存取

  从配置中获取Cacheonix实例
/**
* Tester for CacheManager.
*/
public final class CacheonixTest extends TestCase {

private Cacheonix cacheonix;

/**
* Tests getting an instance of CacheManager using a default Cacheonix configuration.
*/
public void testGetInstance() {

assertNotNull("Cacheonix created in setUp() method should not be null", cacheonix);
}

/**
* Sets up the fixture. This method is called before a test is executed.
* <p/>
* Cacheonix receives the default configuration from a <code>cacheonix-config.xml</code> found in a class path or
* using a file that name is defined by system parameter <code>cacheonix.config.xml<code>.
*/
protected void setUp() throws Exception {

super.setUp();

// Get Cacheonix using a default Cacheonix configuration. The configuration
// is stored in the conf/cacheonix-config.xml
cacheonix = Cacheonix.getInstance();
}

/**
* Tears down the fixture. This method is called after a test is executed.
*/
protected void tearDown() throws Exception {

// Cache manager has be be shutdown upon application exit.
// Note that call to shutdown() here uses unregisterSingleton
// set to true. This is necessary to support clean restart on setUp()
cacheonix.shutdown(ShutdownMode.GRACEFUL_SHUTDOWN, true);
cacheonix = null;

super.tearDown();
}
}


  读取缓存
Cacheonix cacheonix = Cacheonix.getInstance();
Cache<String, String> cache = cacheonix.getCache("my.cache");
String cachedValue = cache.get("my.key");


  设置缓存
Cacheonix cacheonix = Cacheonix.getInstance();
Cache<String, String> cache = cacheonix.getCache("my.cache");
String replacedValue = cache.put("my.key", "my.value");


  删除缓存
Cacheonix cacheonix = Cacheonix.getInstance();
Cache<String, String> cache = cacheonix.getCache("my.cache");
String removedValue = cache.remove("my.key");


  Cacheonix作为一款开源的分布式缓存框架,可以满足中型企业规模的系统架构,对提升系统性能有非常棒的作用。

JBoss

  集群高可用性

  JBoss Cache将会自动复制缓存数据,并且在集群中的服务器之间进行缓存数据的同步,这样可以保证任何一台服务器重启了都不会影响缓存的可用性。

  集群缓存可避免系统瓶颈

  JBoss Cache顾名思义是利用缓存来提高系统扩展性的,当我们的WEB系统遇到大量的数据库读写时,系统的瓶颈将会出现在数据库端,JBoss Cache正好可以解决数据库的频繁读取问题,解决这个瓶颈。

  另外,由于JBoss Cache的缓存是在集群中的每一个服务器间同步的,因此也不会因为一台缓存服务器遇到性能问题而影响整个系统。

  JBoss Cache的standalone用法

  首先是初始化TreeCache
TreeCache tree = new TreeCache();


  然后是读进配置文件
PropertyConfigurator config = new PropertyConfigurator();
config.configure("配置文件.xml");


  然后开始服务
Tree.startService();


  因为Tree的结构是用NODE来Access的,TreeCache这里就很简单的用:

  /level1/level2/node1 来表示两级Tree下面的Node1。

  现在我们添加几个要Cache的对象。
Tree.put("/level1/level2/node1", "key1", "value1");
String[] array = { "1", "2", "3", "4" }
Tree.put("/level3/array/", "myarray", array);


  大家可以看到,TreeCache里面可以存储任何种类的对象,包括所有复杂对象。

  读取对象就很方便了,
String s = (String)Tree.get("/level1/level2/node1/", "key1");


  value1就读出来了。

  同理:
String[] sarr = (String[]) Tree.get("/level3/array/","myarray");


  System.out.println(sarr[1]) 会显示2

  最后停止服务:
Tree.stopService();


  JBoss Cache的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


  总结

  JBoss Cache还有更多的用法,如果你的系统遇到数据库瓶颈问题,可以考虑使用JBoss Cache来解决。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: