1.将程序或系统经常要调用的对象存在内存(某些资源或者数据会被频繁的使用放入内存中),缓存是一种典型的空间换时间的方案。减少系统开销,提高系统效率,(缓存就是把一些外存上的数据保存到内存)
2.文件缓存:xml,
3.内存缓存:一个static的map,cache
3.自定义缓存:------
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import net.blogjava.frankiegao123.log.slf4j.Log;
import net.blogjava.frankiegao123.log.slf4j.LogFactory;
/**
* <p>System.Config 配置缓存</p>
*
* @author frankiegao123
* 2010-6-10 下午02:48:35
*/
@Component("configCache")
public class ConfigCache implements ConfigService {
private final static Log log = LogFactory.getLog(ConfigCache.class);
/**
* 更新缓存时记录的时间
*/
private volatile long time = 0L;
/**
* 正在更新缓存时的门闩,为 true 时表示当前没有更新缓存,为 true 时表示当前正在更新缓存
*/
private volatile boolean updateGate = true;
/**
* 缓存容器
*/
private Map<String, SysConfig> cache = new ConcurrentHashMap<String, SysConfig>();
private CommonDao commonDao;
@Autowired
public ConfigCache(CommonDao commonDao) {
this.commonDao = commonDao;
log.info("initializing cache...");
refreshCache();
time = System.currentTimeMillis();
log.info("initialized cache finished, cache size: {}, set cache time to current: {}, cache timeout: {}ms", cache.size(), time, ConfigConstant.CACHE_TIMEOUT);
}
/**
* <p>根据配置的键名获取配置值</p>
*
* @param configKey
* @return
* @author frankiegao123
* 2010-6-10 上午11:18:33
*/
public SysConfig getSysConfig(String configKey) {
long current = System.currentTimeMillis();
if(updateGate && isTimeout(current)) {
synchronized (this) {
if(updateGate) {
timeoutSynRefresh(current);
}
}
}
return cache.get(configKey);
}
/**
* <p>超时时更新缓存。该方法需要在同步环境中调用</p>
* @param current
* @author frankiegao123
* 2010-6-10 上午11:16:30
*/
private void timeoutSynRefresh(long current) {
updateGate = false;
log.info("refresh cache start..., time out: {}, size: {}, set updateGate to false", (current - time) / 1000.0, cache.size());
try {
refreshCache();
time = current;
log.info("refresh cache finished, size after update: {}, set cache time to current: {}", cache.size(), String.valueOf(time));
} catch (Exception e) {
log.error("refresh cache failed", e);
} finally {
updateGate = true;
log.info("refresh cache finished, set updateGate to true");
}
}
/**
* <p>更新缓存数据</p>
*
* @author frankiegao123
* 2010-6-10 上午11:15:55
*/
private void refreshCache() {
List<SysConfig> configs = commonDao.getSysConfigs();
for(Iterator<SysConfig> i = configs.iterator(); i.hasNext(); ) {
SysConfig config = i.next();
cache.put(config.getKey(), config);
}
commonDao.clear();
SysConfig config = cache.get(SysConfig.TEST_KEY);
if(config == null) {
log.error("refresh cache, cannot find TEST_KEY");
} else {
log.info("refresh cache, find TEST_KEY = [{}]", config.getValue());
}
}
/**
* <p>缓存是否超时</p>
*
* @param current
* @return
* @author frankiegao123
* 2010-6-10 上午11:16:12
*/
private boolean isTimeout(long current) {
return (current - time >= ConfigConstant.CACHE_TIMEOUT);
}
Collection<SysConfig> getSysConfigs() {
return Collections.unmodifiableCollection(cache.values());
}
int getSize() {
return cache.size();
}
long getTime() {
return time;
}
boolean isUpdateGate() {
return updateGate;
}
void refresh() {
time = 0L;
log.info("refresh: reset cache time to 0");
getSysConfig("none");
log.info("refresh: refresh cache finished, cache: {0}", String.valueOf(time));
}
}
4.ehcache缓存:一个纯Java的进程内缓存框架
4.1xml文件配置:
<ehcache>
<!-- 指定一个文件目录,当EHCache把数据写到硬盘上时,将把数据写到这个文件目录下 -->
<diskStore path="java.io.tmpdir"/>
<!-- 设定缓存的默认数据过期策略 -->
<defaultCache
maxElementsInMemory="10000"
eternal="false"
overflowToDisk="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"/>
<!--
设定具体的命名缓存的数据过期策略
cache元素的属性:
name:缓存名称
maxElementsInMemory:内存中最大缓存对象数
maxElementsOnDisk:硬盘中最大缓存对象数,若是0表示无穷大
eternal:true表示对象永不过期,此时会忽略timeToIdleSeconds和timeToLiveSeconds属性,默认为false
overflowToDisk:true表示当内存缓存的对象数目达到了maxElementsInMemory界限后,会把溢出的对象写到硬盘缓存中。注意:如果缓存的对象要写入到硬盘中的话,则该对象必须实现了Serializable接口才行。
diskSpoolBufferSizeMB:磁盘缓存区大小,默认为30MB。每个Cache都应该有自己的一个缓存区。
diskPersistent:是否缓存虚拟机重启期数据
diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认为120秒
timeToIdleSeconds: 设定允许对象处于空闲状态的最长时间,以秒为单位。当对象自从最近一次被访问后,如果处于空闲状态的时间超过了timeToIdleSeconds属性值,这个对象就会过期,EHCache将把它从缓存中清空。只有当eternal属性为false,该属性才有效。如果该属性值为0,则表示对象可以无限期地处于空闲状态
timeToLiveSeconds:设定对象允许存在于缓存中的最长时间,以秒为单位。当对象自从被存放到缓存中后,如果处于缓存中的时间超过了 timeToLiveSeconds属性值,这个对象就会过期,EHCache将把它从缓存中清除。只有当eternal属性为false,该属性才有效。如果该属性值为0,则表示对象可以无限期地存在于缓存中。timeToLiveSeconds必须大于timeToIdleSeconds属性,才有意义
memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。可选策略有:LRU(最近最少使用,默认策略)、FIFO(先进先出)、LFU(最少访问次数)。
-->
<cache name="CACHE1"
maxElementsInMemory="1000"
eternal="true"
overflowToDisk="true"/>
<cache name="CACHE2"
maxElementsInMemory="1000"
eternal="false"
timeToIdleSeconds="200"
timeToLiveSeconds="4000"
overflowToDisk="true"/>
</ehcache>
4.2 配置文件介绍(分布式缓存)
1)RMI集群模式
A、手工发现
需要指定节点发现模式peerDiscovery值为manual,rmiUrls设置为另一台服务器的IP、端口和缓存名等信息。
- <cacheManagerPeerProviderFactory
- class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
- properties="peerDiscovery=manual,
- rmiUrls=//192.168.0.12:4567/oschina_cache|//192.168.0.13:4567/oschina_cache"
- />
B、自动发现
需要指定节点发现模式peerDiscovery值为automatic自动,同时组播地址可以指定D类IP地址空间,范围从 224.0.1.0 到 238.255.255.255 中的任何一个地址。
- <cacheManagerPeerProviderFactory
- class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
- properties="peerDiscovery=automatic, multicastGroupAddress=230.0.0.1,
- multicastGroupPort=4446, timeToLive=32"
- />
需要在每个cache属性中加入
<cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"/>
- <cache name="demoCache"
- maxElementsInMemory="10000"
- eternal="true"
- overflowToDisk="true">
- <cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"/>
- </cache>
通过编程方式使用EhCache
- //从classes目录查找ehcache.xml配置文件
- CacheManager cacheManager = CacheManager.getInstance();
- //从classes目录查找指定名称的配置文件
- //CacheManager cacheManager = CacheManager.create(getClass().getResource("/ehcache.xml"));
- //根据配置文件获得Cache实例
- Cache cache = cacheManager.getCache("CACHE1");
- //清空Cache中的所有元素
- cache.removeAll();
- //往Cache中添加元素
- cache.put(new Element("s1", "11111"));
- cache.put(new Element("s2", "22222"));
- cache.put(new Element("s3", "33333"));
- //从Cache中取得元素
- Element e = cache.get("s3");
- System.out.println(e.getValue());
- //卸载缓存管理器
- cacheManager.shutdown();
5、页面缓存
在web.xml文件中配置过滤器。此处对test_tag.jsp页面进行缓存。
- <filter>
- <filter-name>testPageCachingFilter</filter-name>
- <filter-class>net.sf.ehcache.constructs.web.filter.SimplePageCachingFilter</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>testPageCachingFilter</filter-name>
- <url-pattern>/test_tag.jsp</url-pattern>
- </filter-mapping>
在ehcache.xml文件中配置Cache节点。注意:cache的name属性必需为SimplePageCachingFilter。
- <cache name="SimplePageCachingFilter"
- maxElementsInMemory="10"
- overflowToDisk="true"
- eternal="false"
- timeToIdleSeconds="100"
- timeToLiveSeconds="100"
- memoryStoreEvictionPolicy="LFU" />