From ed350693e395b8cdafa194f2ac1443611067d04e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=82=B1=E5=AE=B6=E6=A6=86?= Date: Tue, 1 Nov 2016 19:10:43 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0JedisCluster=E7=9A=84?= =?UTF-8?q?=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- .../cache/admin/servlet/AdminServlet.java | 13 +- .../comparator/AutoLoadOldestComparator.java | 3 +- .../com/jarvis/cache/map/CachePointCut.java | 4 +- .../cache/redis/JedisClusterCacheManager.java | 182 ++++++++++++++++++ .../generics/ParameterizedTypeImpl.java | 6 +- .../cache/serializer/StringSerializer.java | 3 +- .../java/com/jarvis/lib/util/BeanUtil.java | 5 +- 8 files changed, 196 insertions(+), 22 deletions(-) create mode 100644 src/main/java/com/jarvis/cache/redis/JedisClusterCacheManager.java diff --git a/pom.xml b/pom.xml index 48a55f88..d9a07aac 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 com.github.qiujiayu autoload-cache - 4.16 + 4.17 jar AutoLoadCache User AOP and annotation to do with cache. diff --git a/src/main/java/com/jarvis/cache/admin/servlet/AdminServlet.java b/src/main/java/com/jarvis/cache/admin/servlet/AdminServlet.java index c2c37a0a..5f165881 100644 --- a/src/main/java/com/jarvis/cache/admin/servlet/AdminServlet.java +++ b/src/main/java/com/jarvis/cache/admin/servlet/AdminServlet.java @@ -161,8 +161,7 @@ private void printHtmlHead(HttpServletResponse resp, String cacheManagerName) th html.append("").append("").append("Cache Admin"); html.append(""); html.append(""); @@ -223,8 +222,7 @@ private void printForm(HttpServletResponse resp, String cacheManagerName, String html.append(""); html.append(""); html.append(""); - html.append( - "cache key: "); + html.append("cache key: "); html.append("
"); html.append(""); html.append(""); @@ -280,8 +278,7 @@ private void printList(HttpServletRequest req, HttpServletResponse resp, Abstrac html.append(" " + getDateFormat(tmpTO.getFirstRequestTime()) + ""); html.append(" " + tmpTO.getRequestTimes() + "次"); html.append(" " + getDateFormat(tmpTO.getLastLoadTime() + tmpTO.getCache().expire() * 1000) + "(" + tmpTO.getCache().expire() + "秒)"); - html.append( - " " + getDateFormat(tmpTO.getLastRequestTime() + tmpTO.getCache().requestTimeout() * 1000) + "(" + tmpTO.getCache().requestTimeout() + "秒)"); + html.append(" " + getDateFormat(tmpTO.getLastRequestTime() + tmpTO.getCache().requestTimeout() * 1000) + "(" + tmpTO.getCache().requestTimeout() + "秒)"); html.append(" " + getDateFormat(tmpTO.getLastLoadTime()) + ""); html.append(" " + tmpTO.getLoadCnt() + "次"); html.append(" " + tmpTO.getAverageUseTime() + "毫秒"); @@ -290,8 +287,8 @@ private void printList(HttpServletRequest req, HttpServletResponse resp, Abstrac html.append(" 重置最后加载时间"); html.append(""); if(null != tmpTO.getArgs() && tmpTO.getArgs().length > 0) { - html.append("show args values"); + html.append("show args values"); } html.append(""); html.append(" "); diff --git a/src/main/java/com/jarvis/cache/comparator/AutoLoadOldestComparator.java b/src/main/java/com/jarvis/cache/comparator/AutoLoadOldestComparator.java index 830bf226..2a17a7a9 100644 --- a/src/main/java/com/jarvis/cache/comparator/AutoLoadOldestComparator.java +++ b/src/main/java/com/jarvis/cache/comparator/AutoLoadOldestComparator.java @@ -5,8 +5,7 @@ import com.jarvis.cache.to.AutoLoadTO; /** - * 排序算法:越接近过期时间,越耗时的排在最前,即: System.currentTimeMillis() - autoLoadTO.getLastLoadTime()-autoLoadTO.getExpire()*1000 值越大,排在越前 - * autoLoadTO.getAverageUseTime() 值越大,排在越前 + * 排序算法:越接近过期时间,越耗时的排在最前,即: System.currentTimeMillis() - autoLoadTO.getLastLoadTime()-autoLoadTO.getExpire()*1000 值越大,排在越前 autoLoadTO.getAverageUseTime() 值越大,排在越前 * @author jiayu.qiu */ public class AutoLoadOldestComparator implements Comparator { diff --git a/src/main/java/com/jarvis/cache/map/CachePointCut.java b/src/main/java/com/jarvis/cache/map/CachePointCut.java index d56763ce..15f2321b 100644 --- a/src/main/java/com/jarvis/cache/map/CachePointCut.java +++ b/src/main/java/com/jarvis/cache/map/CachePointCut.java @@ -19,7 +19,7 @@ * @author jiayu.qiu */ public class CachePointCut extends AbstractCacheManager { - + private static final Logger logger=Logger.getLogger(CachePointCut.class); private final ConcurrentHashMap cache=new ConcurrentHashMap(); @@ -117,7 +117,7 @@ public void setCache(final CacheKeyTO cacheKeyTO, final CacheWrapper res if(tmpObj instanceof ConcurrentHashMap) { hash=(ConcurrentHashMap>>)tmpObj; } else { - logger.error(method.getClass().getName()+"."+method.getName()+"中key为"+cacheKey+"的缓存,已经被占用,请删除缓存再试。"); + logger.error(method.getClass().getName() + "." + method.getName() + "中key为" + cacheKey + "的缓存,已经被占用,请删除缓存再试。"); return; } } diff --git a/src/main/java/com/jarvis/cache/redis/JedisClusterCacheManager.java b/src/main/java/com/jarvis/cache/redis/JedisClusterCacheManager.java new file mode 100644 index 00000000..0adab81d --- /dev/null +++ b/src/main/java/com/jarvis/cache/redis/JedisClusterCacheManager.java @@ -0,0 +1,182 @@ +package com.jarvis.cache.redis; + +import java.lang.reflect.Method; +import java.lang.reflect.Type; + +import org.apache.log4j.Logger; + +import com.jarvis.cache.AbstractCacheManager; +import com.jarvis.cache.exception.CacheCenterConnectionException; +import com.jarvis.cache.script.AbstractScriptParser; +import com.jarvis.cache.serializer.ISerializer; +import com.jarvis.cache.serializer.StringSerializer; +import com.jarvis.cache.to.AutoLoadConfig; +import com.jarvis.cache.to.CacheKeyTO; +import com.jarvis.cache.to.CacheWrapper; + +import redis.clients.jedis.JedisCluster; +import redis.clients.jedis.ShardedJedis; + +/** + * Redis缓存管理 + * @author jiayu.qiu + */ +public class JedisClusterCacheManager extends AbstractCacheManager { + + private static final Logger logger=Logger.getLogger(JedisClusterCacheManager.class); + + private static final StringSerializer keySerializer=new StringSerializer(); + + private JedisCluster jedisCluster; + + /** + * Hash的缓存时长:等于0时永久缓存;大于0时,主要是为了防止一些已经不用的缓存占用内存;hashExpire小于0时,则使用@Cache中设置的expire值(默认值为-1)。 + */ + private int hashExpire=-1; + + /** + * 是否通过脚本来设置 Hash的缓存时长 + */ + private boolean hashExpireByScript=false; + + public JedisClusterCacheManager(AutoLoadConfig config, ISerializer serializer, AbstractScriptParser scriptParser) { + super(config, serializer, scriptParser); + } + + private void returnResource(ShardedJedis shardedJedis) { + shardedJedis.close(); + } + + @Override + public void setCache(final CacheKeyTO cacheKeyTO, final CacheWrapper result, final Method method, final Object args[]) throws CacheCenterConnectionException { + if(null == jedisCluster || null == cacheKeyTO) { + return; + } + String cacheKey=cacheKeyTO.getCacheKey(); + if(null == cacheKey || cacheKey.length() == 0) { + return; + } + ShardedJedis shardedJedis=null; + try { + int expire=result.getExpire(); + String hfield=cacheKeyTO.getHfield(); + if(null == hfield || hfield.length() == 0) { + if(expire == 0) { + + jedisCluster.set(keySerializer.serialize(cacheKey), getSerializer().serialize(result)); + } else { + jedisCluster.setex(keySerializer.serialize(cacheKey), expire, getSerializer().serialize(result)); + } + } else { + hashSet(cacheKey, hfield, result); + } + } catch(Exception ex) { + logger.error(ex.getMessage(), ex); + } finally { + returnResource(shardedJedis); + } + } + + private void hashSet(String cacheKey, String hfield, CacheWrapper result) throws Exception { + byte[] key=keySerializer.serialize(cacheKey); + byte[] field=keySerializer.serialize(hfield); + byte[] val=getSerializer().serialize(result); + int hExpire; + if(hashExpire < 0) { + hExpire=result.getExpire(); + } else { + hExpire=hashExpire; + } + if(hExpire == 0) { + jedisCluster.hset(key, field, val); + } else { + jedisCluster.hset(key, field, val); + jedisCluster.expire(key, hExpire); + } + } + + @SuppressWarnings("unchecked") + @Override + public CacheWrapper get(final CacheKeyTO cacheKeyTO, final Method method, final Object args[]) throws CacheCenterConnectionException { + if(null == jedisCluster || null == cacheKeyTO) { + return null; + } + String cacheKey=cacheKeyTO.getCacheKey(); + if(null == cacheKey || cacheKey.length() == 0) { + return null; + } + CacheWrapper res=null; + ShardedJedis shardedJedis=null; + try { + byte bytes[]=null; + String hfield=cacheKeyTO.getHfield(); + if(null == hfield || hfield.length() == 0) { + bytes=jedisCluster.get(keySerializer.serialize(cacheKey)); + } else { + bytes=jedisCluster.hget(keySerializer.serialize(cacheKey), keySerializer.serialize(hfield)); + } + Type returnType=method.getGenericReturnType(); + res=(CacheWrapper)getSerializer().deserialize(bytes, returnType); + } catch(Exception ex) { + logger.error(ex.getMessage(), ex); + } finally { + returnResource(shardedJedis); + } + return res; + } + + /** + * 根据缓存Key删除缓存 + * @param cacheKeyTO 缓存Key + */ + @Override + public void delete(CacheKeyTO cacheKeyTO) throws CacheCenterConnectionException { + if(null == jedisCluster || null == cacheKeyTO) { + return; + } + String cacheKey=cacheKeyTO.getCacheKey(); + if(null == cacheKey || cacheKey.length() == 0) { + return; + } + logger.debug("delete cache:" + cacheKey); + try { + String hfield=cacheKeyTO.getHfield(); + if(null == hfield || hfield.length() == 0) { + jedisCluster.del(keySerializer.serialize(cacheKey)); + } else { + jedisCluster.hdel(keySerializer.serialize(cacheKey), keySerializer.serialize(hfield)); + } + this.getAutoLoadHandler().resetAutoLoadLastLoadTime(cacheKeyTO); + } catch(Exception ex) { + logger.error(ex.getMessage(), ex); + } finally { + } + } + + public JedisCluster getJedisCluster() { + return jedisCluster; + } + + public void setJedisCluster(JedisCluster jedisCluster) { + this.jedisCluster=jedisCluster; + } + + public int getHashExpire() { + return hashExpire; + } + + public void setHashExpire(int hashExpire) { + if(hashExpire < 0) { + return; + } + this.hashExpire=hashExpire; + } + + public boolean isHashExpireByScript() { + return hashExpireByScript; + } + + public void setHashExpireByScript(boolean hashExpireByScript) { + this.hashExpireByScript=hashExpireByScript; + } +} diff --git a/src/main/java/com/jarvis/cache/reflect/generics/ParameterizedTypeImpl.java b/src/main/java/com/jarvis/cache/reflect/generics/ParameterizedTypeImpl.java index d1331887..761196ee 100644 --- a/src/main/java/com/jarvis/cache/reflect/generics/ParameterizedTypeImpl.java +++ b/src/main/java/com/jarvis/cache/reflect/generics/ParameterizedTypeImpl.java @@ -64,8 +64,7 @@ public boolean equals(Object paramObject) { Type localType1=localParameterizedType.getOwnerType(); Type localType2=localParameterizedType.getRawType(); - return (this.ownerType == null ? localType1 == null : this.ownerType.equals(localType1)) - && (this.rawType == null ? localType2 == null : this.rawType.equals(localType2)) + return (this.ownerType == null ? localType1 == null : this.ownerType.equals(localType1)) && (this.rawType == null ? localType2 == null : this.rawType.equals(localType2)) && (Arrays.equals(this.actualTypeArguments, localParameterizedType.getActualTypeArguments())); } @@ -73,8 +72,7 @@ public boolean equals(Object paramObject) { } public int hashCode() { - return Arrays.hashCode(this.actualTypeArguments) ^ (this.ownerType == null ? 0 : this.ownerType.hashCode()) - ^ (this.rawType == null ? 0 : this.rawType.hashCode()); + return Arrays.hashCode(this.actualTypeArguments) ^ (this.ownerType == null ? 0 : this.ownerType.hashCode()) ^ (this.rawType == null ? 0 : this.rawType.hashCode()); } public String toString() { diff --git a/src/main/java/com/jarvis/cache/serializer/StringSerializer.java b/src/main/java/com/jarvis/cache/serializer/StringSerializer.java index cb97ae27..37bff318 100644 --- a/src/main/java/com/jarvis/cache/serializer/StringSerializer.java +++ b/src/main/java/com/jarvis/cache/serializer/StringSerializer.java @@ -5,8 +5,7 @@ import java.nio.charset.Charset; /** - * Simple String to byte[] (and back) serializer. Converts Strings into bytes and vice-versa using the specified charset (by default - * UTF-8). + * Simple String to byte[] (and back) serializer. Converts Strings into bytes and vice-versa using the specified charset (by default UTF-8). *

* Useful when the interaction with the Redis happens mainly through Strings. *

diff --git a/src/main/java/com/jarvis/lib/util/BeanUtil.java b/src/main/java/com/jarvis/lib/util/BeanUtil.java index a73cdbd2..de6260e4 100644 --- a/src/main/java/com/jarvis/lib/util/BeanUtil.java +++ b/src/main/java/com/jarvis/lib/util/BeanUtil.java @@ -28,9 +28,8 @@ public class BeanUtil { * @return boolean true or false */ public static boolean isPrimitive(Object obj) { - boolean rv=obj.getClass().isPrimitive() || obj instanceof String || obj instanceof Integer || obj instanceof Long || obj instanceof Byte - || obj instanceof Character || obj instanceof Boolean || obj instanceof Short || obj instanceof Float || obj instanceof Double || obj instanceof BigDecimal - || obj instanceof BigInteger; + boolean rv=obj.getClass().isPrimitive() || obj instanceof String || obj instanceof Integer || obj instanceof Long || obj instanceof Byte || obj instanceof Character || obj instanceof Boolean + || obj instanceof Short || obj instanceof Float || obj instanceof Double || obj instanceof BigDecimal || obj instanceof BigInteger; return rv; }