package org.musicmaster.yulin.ercache;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import net.sf.ehcache.Element;
import org.musicmaster.yulin.business.impl.UserServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.Cache;
import org.springframework.cache.support.SimpleValueWrapper;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
/**
* 两级缓存,一级:ehcache,二级为redisCache
* @author yulin
*
*/
public class EhRedisCache implements Cache{
private static final Logger LOG = LoggerFactory.getLogger(UserServiceImpl.class);
private String name;
/*** 一定容量的LRU队列*/
private net.sf.ehcache.Cache ehCache;
/*** 无容量限制key带时效性*/
private RedisTemplate<String, Object> redisTemplate;
private long liveTime = 1; //默认1h=1*60*60
private int activeCount = 10;
@Override
public String getName() {
return this.name;
}
@Override
public Object getNativeCache() {
return this;
}
@Override
public ValueWrapper get(Object key) {
Element value = ehCache.get(key);
LOG.info("Cache L1 (ehcache) :{}={}",key,value);
if (value!=null) {
//TODO 访问10次EhCache 强制访问一次redis 使得数据不失效
if(value.getHitCount() < activeCount){
return (value != null ? new SimpleValueWrapper(value.getObjectValue()) : null);
}else{
value.resetAccessStatistics();
}
}
final String keyStr = key.toString();
Object objectValue = redisTemplate.execute(new RedisCallback<Object>() {
public Object doInRedis(RedisConnection connection)
throws DataAccessException {
byte[] key = keyStr.getBytes();
byte[] value = connection.get(key);
if (value == null) {
//
return null;
}
//每次获得延迟时间
if (liveTime > 0) {
connection.expire(key, liveTime);
}
return toObject(value);
}
},true);
ehCache.put(new Element(key, objectValue));//取出来之后缓存到本地
LOG.info("Cache L2 (redis) :{}={}",key,objectValue);
return (objectValue != null ? new SimpleValueWrapper(objectValue) : null);
}
@Override
public void put(Object key, Object value) {
ehCache.put(new Element(key, value));
final String keyStr = key.toString();
final Object valueStr = value;
redisTemplate.execute(new RedisCallback<Long>() {
public Long doInRedis(RedisConnection connection)
throws DataAccessException {
byte[] keyb = keyStr.getBytes();
byte[] valueb = toByteArray(valueStr);
connection.set(keyb, valueb);
if (liveTime > 0) {
connection.expire(keyb, liveTime);
}
return 1L;
}
},true);
}
@Override
public void evict(Object key) {
ehCache.remove(key);
final String keyStr = key.toString();
redisTemplate.execute(new RedisCallback<Long>() {
public Long doInRedis(RedisConnection connection)
throws DataAccessException {
return connection.del(keyStr.getBytes());
}
},true);
}
@Override
public void clear() {
ehCache.removeAll();
redisTemplate.execute(new RedisCallback<String>() {
public String doInRedis(RedisConnection connection)
throws DataAccessException {
connection.flushDb();
return "clear done.";
}
},true);
}
public net.sf.ehcache.Cache getEhCache() {
return ehCache;
}
public void setEhCache(net.sf.ehcache.Cache ehCache) {
this.ehCache = ehCache;
}
public RedisTemplate<String, Object> getRedisTemplate() {
return redisTemplate;
}
public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
}
public long getLiveTime() {
return liveTime;
}
public void setLiveTime(long liveTime) {
this.liveTime = liveTime;
}
public void setName(String name) {
this.name = name;
}
public int getActiveCount() {
return activeCount;
}
public void setActiveCount(int activeCount) {
this.activeCount = activeCount;
}
private byte[] toByteArray(Object obj) {
byte[] bytes = null;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(obj);
oos.flush();
bytes = bos.toByteArray();
oos.close();
bos.close();
} catch (IOException ex) {
ex.printStackTrace();
}
return bytes;
}
private Object toObject(byte[] bytes) {
Object obj = null;
try {
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bis);
obj = ois.readObject();
ois.close();
bis.close();
} catch (IOException ex) {
ex.printStackTrace();
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
return obj;
}
}
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
两级缓存在redis的方案上做一步优化,在缓存到远程redis的同时,缓存一份到本地进程ehcache(此处的ehcache不用做集群,避免组播带来的开销),取缓存的时候会先取本地,没有会向redis请求,这样会减少应用服务器<–>缓存服务器redis之间的网络开销。(见下图,为了减少get这几条网络传输,我们会在每个应用服务器上增加本地的ehcache缓存作为二级缓存,即第一次get到的数据存入ehcache,后面output输出即可从本地ehcache中获取,不用再访问redis了,所以就减少了以后get的网络开销。get开销只要一次,后续不需要了,除非本地缓存过期需要再get。)
资源推荐
资源详情
资源评论
收起资源包目录
spring-ehcache-redis两级缓存.rar (47个子文件)
ercache
.project 559B
pom.xml 1KB
target
test-classes
org
musicmaster
yulin
ercache
TestEhRedisCache.class 2KB
TestRedisCache.class 1KB
TestEhCache.class 1KB
classes
org
musicmaster
yulin
ercache
BusinessCacheEvict.class 589B
BusinessCacheKeyGenerator.class 3KB
BusinessCacheable.class 586B
EhRedisCache$3.class 1KB
EhRedisCache.class 6KB
EhRedisCache$2.class 2KB
EhRedisCache$4.class 1KB
ListKeyParam.class 175B
EhRedisCache$1.class 2KB
business
UserService.class 1KB
domain
User.class 2KB
User$Sex.class 1KB
impl
UserServiceImpl.class 4KB
util
MD5Util.class 1KB
log4j.properties 1KB
spring-ehRedisCache.xml 3KB
spring-redis.xml 3KB
redis.properties 573B
spring-ehcache.xml 2KB
ehcache.xml 4KB
.settings
org.eclipse.core.resources.prefs 223B
org.eclipse.jdt.core.prefs 736B
org.eclipse.m2e.core.prefs 90B
src
test
java
org
musicmaster
yulin
ercache
TestEhRedisCache.java 2KB
TestRedisCache.java 808B
TestEhCache.java 755B
main
java
org
musicmaster
yulin
ercache
BusinessCacheKeyGenerator.java 2KB
EhRedisCache.java 6KB
ListKeyParam.java 99B
BusinessCacheable.java 548B
BusinessCacheEvict.java 551B
business
UserService.java 487B
domain
User.java 1KB
impl
UserServiceImpl.java 2KB
util
MD5Util.java 1KB
resource
log4j.properties 1KB
spring-ehRedisCache.xml 3KB
spring-redis.xml 3KB
redis.properties 573B
spring-ehcache.xml 2KB
ehcache.xml 4KB
.classpath 1KB
共 47 条
- 1
资源评论
- 啊湘2018-05-03下来看下!!!
gylinjinhai
- 粉丝: 9
- 资源: 27
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功