您的位置:首页 > 编程语言 > Java开发

LocalCache本地缓存分享

2016-03-31 20:17 323 查看



LocalCache本地缓存分享

前言
一、本地缓存应用场景
二、java本地缓存标准
三、java开源缓存框架
四、LocalCache实现
结束语
 
前言
本次分享探讨java平台的本地缓存,是指占用JVM的heap区域来缓冲存储数据的缓存组件。
 
一、本地缓存应用场景


localcache有着极大的性能优势:
1. 单机情况下适当使用localcache会使应用的性能得到很大的提升。
2. 集群环境下对于敏感性要求不高的数据可以使用localcache,只配置简单的失效机制来保证数据的相对一致性。

哪些数据可以存储到本地缓存?
1.访问频繁的数据

2.静态基础数据(长时间内不变的数据);

3.相对静态数据(短时间内不变的数据)。

二、java本地缓存标准
Java缓存新标准(javax.cache),这个标准由JSR107所提出,已经被包含在Java EE 7中。
特性:

1.原子操作,跟java.util.ConcurrentMap类似

2.从缓存中读取

3.写入缓存

4.缓存事件监听器

5.数据统计

6.包含所有隔离(ioslation)级别的事务

7.缓存注解(annotations)

8.保存定义key和值类型的泛型缓存

9.引用保存(只适用于堆缓存)和值保存定义

                  
但目前应用不是很普遍。
 
三、java开源缓存框架
比较有名的本地缓存开源框架有:
1.EHCache
EHCache是一个纯java的在进程中的缓存,它具有以下特性:快速,简单,为Hibernate2.1充当可插入的缓存,最小的依赖性,全面的文档和测试。
BUG: 过期失效的缓存元素无法被GC掉,时间越长缓存越多,内存占用越大,导致内存泄漏的概率越大。

2.OSCache
OSCache有以下特点:缓存任何对象,你可以不受限制的缓存部分jsp页面或HTTP请求,任何java对象都可以缓存。拥有全面的API--OSCache
API给你全面的程序来控制所有的OSCache特性。永久缓存--缓存能随意的写入硬盘,因此允许昂贵的创建(expensive-to-create)数据来保持缓存,甚至能让应用重启。支持集群--集群缓存数据能被单个的进行参数配置,不需要修改代码。缓存记录的过期--你可以有最大限度的控制缓存对象的过期,包括可插入式的刷新策略(如果默认性能不需要时)。

3.JCache
Java缓存新标准(javax.cache)

4.cache4j
cache4j是一个有简单API与实现快速的Java对象缓存。它的特性包括:在内存中进行缓存,设计用于多线程环境,两种实现:同步与阻塞,多种缓存清除策略:LFU,
LRU, FIFO,可使用强引用。

5.ShiftOne
ShiftOne Java Object Cache是一个执行一系列严格的对象缓存策略的Java lib,就像一个轻量级的配置缓存工作状态的框架。

6.WhirlyCache
Whirlycache是一个快速的、可配置的、存在于内存中的对象的缓存。
 
四、LocalCache实现
1、LocalCache简介
LocalCache是一个精简版本地缓存组件,有以下特点:
1.  有容量上限maxCapacity;

2.  缓存达到容量上限时基于LRU策略来移除缓存元素;

3.  缓存对象的生命周期(缓存失效时间)由调用方决定;

4.  缓存对象失效后,将会有定时清理线程来清理掉,不会导致内存泄漏。

5.  性能比Ehcache稍强。

 
2、总体设计
LocalCache总体设计:
1.  缓存元素 CacheElement;

2.  缓存容器 LRULinkedHashMap;

3.  缓存接口 Cache;

4.  缓存组件实现 LocalCache。

3、详细设计
1.  CacheElement设计

 /**
* 缓存元素
*
*/
public class CacheElement {
private Object key;
private Object value;
private long createTime;
private long lifeTime;
private int hitCount;

public CacheElement() {
}

public CacheElement(Object key ,Object value) {
this.key = key;
this.value = value;
this.createTime = System.currentTimeMillis();
}

public Object getKey(
c337
) {
return key;
}

public void setKey(Object key) {
this.key = key;
}

public Object getValue() {
hitCount++;
return value;
}

public void setValue(Object value) {
this.value = value;
}

public long getCreateTime() {
return createTime;
}

public void setCreateTime(long createTime) {
this.createTime = createTime;
}

public int getHitCount() {
return hitCount;
}

public void setHitCount(int hitCount) {
this.hitCount = hitCount;
}

public long getLifeTime() {
return lifeTime;
}

public void setLifeTime(long lifeTime) {
this.lifeTime = lifeTime;
}

public boolean isExpired() {
boolean isExpired = System.currentTimeMillis() - getCreateTime() > getLifeTime();
return isExpired;
}

/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("[ key=").append(key).append(", isExpired=").append(isExpired())
.append(", lifeTime=").append(lifeTime).append(", createTime=").append(createTime)
.append(", hitCount=").append(hitCount)
.append(", value=").append(value).append(" ]");
return sb.toString();
}

/*
* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
public final int hashCode(){
if(null == key){
return "".hashCode();
}
return this.key.hashCode();
}

/*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
public final boolean equals(Object object) {
if ((object == null) || (!(object instanceof CacheElement))) {
return false;
}

CacheElement element = (CacheElement) object;
if ((this.key == null) || (element.getKey() == null)) {
return false;
}

return this.key.equals(element.getKey());
}
}


2.  LRULinkedHashMap实现

 
import java.util.LinkedHashMap;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 实现 LRU策略的 LinkedHashMap
*
* @param
* @param
*/
public class LRULinkedHashMap extends LinkedHashMap
{
protected static final long serialVersionUID = 2828675280716975892L;

protected static final int DEFAULT_MAX_ENTRIES = 100;

protected final int initialCapacity;
protected final int maxCapacity;
protected boolean enableRemoveEldestEntry = true;//是否允许自动移除比较旧的元素(添加元素时)

protected static final float DEFAULT_LOAD_FACTOR = 0.8f;
protected final Lock lock = new ReentrantLock();

public LRULinkedHashMap(int initialCapacity)
{
this(initialCapacity, DEFAULT_MAX_ENTRIES);
}

public LRULinkedHashMap(int initialCapacity ,int maxCapacity)
{
//set accessOrder=true, LRU
super(initialCapacity, DEFAULT_LOAD_FACTOR, true);

this.initialCapacity = initialCapacity;
this.maxCapacity = maxCapacity;
}

/*
* (non-Javadoc)
* @see java.util.LinkedHashMap#removeEldestEntry(java.util.Map.Entry)
*/
protected boolean removeEldestEntry(java.util.Map.Entry eldest)
{
return enableRemoveEldestEntry && ( size() > maxCapacity );
}

/*
* (non-Javadoc)
* @see java.util.LinkedHashMap#get(java.lang.Object)
*/
public V get(Object key)
{
try {
lock.lock();
return super.get(key);
}
finally {
lock.unlock();
}
}

/*
* (non-Javadoc)
* @see java.util.HashMap#put(java.lang.Object, java.lang.Object)
*/
public V put(K key, V value)
{
try {
lock.lock();
return super.put(key, value);
}
finally {
lock.unlock();
}
}

/*
* (non-Javadoc)
* @see java.util.HashMap#remove(java.lang.Object)
*/
public V remove(Object key) {
try {
lock.lock();
return super.remove(key);
}
finally {
lock.unlock();
}
}

/*
* (non-Javadoc)
* @see java.util.LinkedHashMap#clear()
*/
public void clear() {
try {
lock.lock();
super.clear();
}
finally {
lock.unlock();
}
}

/*
* (non-Javadoc)
* @see java.util.HashMap#keySet()
*/
public Set keySet() {
try {
lock.lock();
return super.keySet();
}
finally {
lock.unlock();
}
}

public boolean isEnableRemoveEldestEntry() {
return enableRemoveEldestEntry;
}
public void setEnableRemoveEldestEntry(boolean enableRemoveEldestEntry) {
this.enableRemoveEldestEntry = enableRemoveEldestEntry;
}
public int getInitialCapacity() {
return initialCapacity;
}
public int getMaxCapacity() {
return maxCapacity;
}
}


3.  Cache接口设计

 /**
* 缓存接口
*
*/
public interface Cache {

/**
* 获取缓存
* @param key
* @return
*/
public T getCache(Object key);

/**
* 缓存对象
* @param key
* @param value
* @param milliSecond 缓存生命周期(毫秒)
*/
public void putCache(Object key, Object value ,Long milliSecond);

/**
* 缓存容器中是否包含 key
* @param key
* @return
*/
public boolean containsKey(Object key);

/**
* 缓存列表大小
* @return
*/
public int getSize();

/**
* 是否启用缓存
*/
public boolean isEnabled();
/**
* 启用 或 停止
* @param enable
*/
public void setEnabled(boolean enabled);

/**
* 移除所有缓存
*/
public void invalidateCaches();

/**
* 移除 指定key缓存
* @param key
*/
public void invalidateCache(Object key);
}


4.  LocalCache实现

 import java.util.Date;
import java.util.Iterator;
import java.util.Random;

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

/**
* 本地缓存组件
*/
public class LocalCache implements Cache{
private Logger logger = LoggerFactory.getLogger(this.getClass());

private LRULinkedHashMap
 
结束语
开源或有BUG,入手需谨慎。             
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  缓存 java 框架 开源