LocalCache本地缓存分享

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实现

1LocalCache简介

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() {
		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,入手需谨慎。             

你可能感兴趣的:(cache,open-source)