|
|
package com.yoho.activity.common.redis;
|
|
|
|
|
|
import java.nio.charset.Charset;
|
|
|
import java.util.Collection;
|
|
|
import java.util.HashMap;
|
|
|
import java.util.HashSet;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
|
import java.util.Map.Entry;
|
|
|
import java.util.Set;
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
|
|
import javax.annotation.Resource;
|
|
|
|
|
|
import org.apache.commons.collections.CollectionUtils;
|
|
|
import org.apache.commons.collections.MapUtils;
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
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.ZSetOperations.TypedTuple;
|
|
|
|
|
|
import com.alibaba.fastjson.JSON;
|
|
|
import com.google.common.collect.Lists;
|
|
|
import com.google.common.collect.Maps;
|
|
|
import com.yoho.core.config.ConfigReader;
|
|
|
import com.yoho.core.redis.YHListOperations;
|
|
|
import com.yoho.core.redis.YHRedisTemplate;
|
|
|
import com.yoho.core.redis.YHValueOperations;
|
|
|
import com.yoho.core.redis.YHZSetOperations;
|
|
|
|
|
|
/**
|
|
|
* @author xieyong
|
|
|
*
|
|
|
*/
|
|
|
public abstract class AbstractGracefulRedisTemplate{
|
|
|
|
|
|
// 缓存统计信息打印,本身logback是异步打印,不需要自己起线程异步去打印了
|
|
|
private final Logger logger = LoggerFactory.getLogger("cacheStatistic");
|
|
|
|
|
|
private final Logger redisTimeOutLogger = LoggerFactory.getLogger("redisTimeOut");
|
|
|
|
|
|
private final static Logger warnLogger = LoggerFactory.getLogger(GracefulRedisTemplate.class);
|
|
|
|
|
|
private final static Integer TIMEOUT_THRESHOLD = 50;
|
|
|
|
|
|
private static final Charset CHARSET_UTF_8 = Charset.forName("UTF-8");
|
|
|
|
|
|
@Resource( name = "core-config-reader" )
|
|
|
private ConfigReader configReader;
|
|
|
|
|
|
abstract YHRedisTemplate<String, String> getRedisTemplate();
|
|
|
|
|
|
abstract YHValueOperations<String, String> getValueOperations();
|
|
|
|
|
|
abstract YHListOperations<String, String> getListOperations();
|
|
|
|
|
|
abstract YHZSetOperations<String, String> getZsetOperations();
|
|
|
|
|
|
abstract boolean isAync();
|
|
|
|
|
|
public boolean isCache(){
|
|
|
return configReader.getBoolean("product.degrade.isCache.enable", false);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @param key
|
|
|
* @param value
|
|
|
* @param timeout 默认单位秒
|
|
|
*/
|
|
|
public void setEx(String key, Object value, long timeout) {
|
|
|
if (isCache()) {
|
|
|
return;
|
|
|
}
|
|
|
String redisValue = null;
|
|
|
|
|
|
if (value instanceof String) {
|
|
|
redisValue = (String) value;
|
|
|
} else {
|
|
|
redisValue = JSON.toJSONString(value);
|
|
|
}
|
|
|
try {
|
|
|
//原子命令,如果超过7天,因为twproxy不支持long time,单独用命令实现
|
|
|
if(timeout>604800){
|
|
|
getValueOperations().set(key, redisValue);
|
|
|
this.expire(key, timeout);
|
|
|
}else{
|
|
|
getValueOperations().set(key, redisValue, timeout, TimeUnit.SECONDS);
|
|
|
}
|
|
|
} catch (Exception e) {
|
|
|
warnLogger.warn("add cache failed!!! cachekey is:{}", key, e);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
*
|
|
|
* @param map
|
|
|
* @param timeout
|
|
|
*/
|
|
|
public void mset(Map<String, ? extends Object> map, long timeout) {
|
|
|
if (isCache()) {
|
|
|
return;
|
|
|
}
|
|
|
if (MapUtils.isEmpty(map)) {
|
|
|
return;
|
|
|
}
|
|
|
getRedisTemplate().mset(map, timeout);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @param key
|
|
|
*/
|
|
|
public boolean hasKey(String key) {
|
|
|
if (isCache()) {
|
|
|
return false;
|
|
|
}
|
|
|
try {
|
|
|
// 此处是读的操作
|
|
|
boolean hasKey = getRedisTemplate().hasKey(key);
|
|
|
return hasKey;
|
|
|
} catch (Exception e) {
|
|
|
warnLogger.warn("hasKey cache failed!!! key is: {}", key, e);
|
|
|
}
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* setex命令不支持long expire 需要将这两个命令拆开,拆开之后命令就不是原子性的了,可能会出现set 命令成功 expire命令失败
|
|
|
* 这样就会出现key永久有效的情况
|
|
|
*
|
|
|
* @param key
|
|
|
*/
|
|
|
public void expire(String key, long timeout) {
|
|
|
if (isCache()) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
getRedisTemplate().longExpire(key, timeout, TimeUnit.SECONDS);
|
|
|
} catch (Exception e) {
|
|
|
warnLogger.error("expire cache failed!!! key is: {}", key, e);
|
|
|
// 如果设置有效期失败,将之前塞进去的key删除
|
|
|
this.deleteQuietly(key);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public Long getExpire(String key) {
|
|
|
if (isCache()) { return null; }
|
|
|
try {
|
|
|
return getRedisTemplate().getExpire(key);
|
|
|
} catch (Exception e) {
|
|
|
warnLogger.error("Get expire failed!!! key is: {}", key, e);
|
|
|
}
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
private void deleteQuietly(String key) {
|
|
|
try {
|
|
|
getRedisTemplate().delete(key);
|
|
|
} catch (Exception e) {
|
|
|
warnLogger.error("delete cache failed!!! key is: {}", key, e);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @param key
|
|
|
* @param clazz
|
|
|
* @return 传入的都返回,有数据返回数据,没有数据返回 NULL
|
|
|
*/
|
|
|
public <T> Map<String, T> mget(List<String> keys, Class<T> clazz) {
|
|
|
if (isCache()) {
|
|
|
HashMap<String, T> hashMap = new HashMap<String, T>(keys.size());
|
|
|
for (String key : keys) {
|
|
|
hashMap.put(key, null);
|
|
|
}
|
|
|
return hashMap;
|
|
|
}
|
|
|
try {
|
|
|
List<String> multiGet = getValueOperations().multiGet(keys);
|
|
|
int size = multiGet.size();
|
|
|
Map<String, T> result = new HashMap<String, T>(size);
|
|
|
String curItem;
|
|
|
for (int i = 0; i < size; i++) {
|
|
|
curItem = multiGet.get(i);
|
|
|
if (null == curItem) {
|
|
|
result.put(keys.get(i), null);
|
|
|
} else {
|
|
|
result.put(keys.get(i), getValue(curItem, clazz));
|
|
|
}
|
|
|
}
|
|
|
return result;
|
|
|
} catch (Exception e) {
|
|
|
warnLogger.warn("get from cache failed!!! keys is: {}", keys, e);
|
|
|
HashMap<String, T> hashMap = new HashMap<String, T>(keys.size());
|
|
|
for (String key : keys) {
|
|
|
hashMap.put(key, null);
|
|
|
}
|
|
|
return hashMap;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 获取存在的 map 列表(不含 NULL)
|
|
|
*/
|
|
|
public <T> Map<String, T> multiGetMapNotNULL(List<String> keys, Class<T> clazz) {
|
|
|
if (CollectionUtils.isEmpty(keys)) return null;
|
|
|
Map<String, T> result = mget(keys, clazz);
|
|
|
return Maps.filterEntries(result, entity -> entity.getValue() != null);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
*
|
|
|
* @param keys
|
|
|
* 批量获取int类型的value
|
|
|
* @return
|
|
|
*/
|
|
|
public Map<String, Integer> mgetIntValue(List<String> keys) {
|
|
|
if (isCache()) {
|
|
|
HashMap<String, Integer> hashMap = new HashMap<String, Integer>(keys.size());
|
|
|
for (String key : keys) {
|
|
|
hashMap.put(key, null);
|
|
|
}
|
|
|
return hashMap;
|
|
|
}
|
|
|
try {
|
|
|
List<String> multiGet = getValueOperations().multiGet(keys);
|
|
|
int size = multiGet.size();
|
|
|
Map<String, Integer> result = new HashMap<String, Integer>(size);
|
|
|
String curItem;
|
|
|
for (int i = 0; i < size; i++) {
|
|
|
curItem = multiGet.get(i);
|
|
|
if (null == curItem) {
|
|
|
result.put(keys.get(i), null);
|
|
|
} else {
|
|
|
result.put(keys.get(i), Integer.valueOf(curItem));
|
|
|
}
|
|
|
}
|
|
|
return result;
|
|
|
} catch (Exception e) {
|
|
|
warnLogger.warn("get from cache failed!!! keys is: {}", keys, e);
|
|
|
HashMap<String, Integer> hashMap = new HashMap<String, Integer>(keys.size());
|
|
|
for (String key : keys) {
|
|
|
hashMap.put(key, null);
|
|
|
}
|
|
|
return hashMap;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @param keys
|
|
|
* @param clazz
|
|
|
* @return
|
|
|
*/
|
|
|
public <T> Map<String, List<T>> mgetList(final List<String> keys, final Class<T> clazz) {
|
|
|
if (isCache()) {
|
|
|
HashMap<String, List<T>> hashMap = new HashMap<String, List<T>>(keys.size());
|
|
|
for (String key : keys) {
|
|
|
hashMap.put(key, null);
|
|
|
}
|
|
|
return hashMap;
|
|
|
}
|
|
|
try {
|
|
|
List<String> multiGet = getValueOperations().multiGet(keys);
|
|
|
int size = multiGet.size();
|
|
|
Map<String, List<T>> result = new HashMap<String, List<T>>(size);
|
|
|
String curItem;
|
|
|
for (int i = 0; i < size; i++) {
|
|
|
curItem = multiGet.get(i);
|
|
|
if (null == curItem) {
|
|
|
result.put(keys.get(i), null);
|
|
|
} else {
|
|
|
result.put(keys.get(i), JSON.parseArray(curItem, clazz));
|
|
|
}
|
|
|
}
|
|
|
return result;
|
|
|
} catch (Exception e) {
|
|
|
warnLogger.warn("get from cache failed!!! keys is: {}", keys, e);
|
|
|
HashMap<String, List<T>> hashMap = new HashMap<String, List<T>>(keys.size());
|
|
|
for (String key : keys) {
|
|
|
hashMap.put(key, null);
|
|
|
}
|
|
|
return hashMap;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @param key
|
|
|
* @param value
|
|
|
*/
|
|
|
public void set(String key, Object value) {
|
|
|
if (isCache()) {
|
|
|
return;
|
|
|
}
|
|
|
String redisValue = null;
|
|
|
|
|
|
if (value instanceof String) {
|
|
|
redisValue = (String) value;
|
|
|
} else {
|
|
|
redisValue = JSON.toJSONString(value);
|
|
|
}
|
|
|
try {
|
|
|
getValueOperations().set(key, redisValue);
|
|
|
} catch (Exception e) {
|
|
|
warnLogger.warn("add cache failed!!! cachekey is:{}", key, e);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 有序set的单个元素插入
|
|
|
*
|
|
|
* @param key
|
|
|
* @param value
|
|
|
*/
|
|
|
public void setSortedSet(String key, Object value, double score) {
|
|
|
if (isCache()) {
|
|
|
return;
|
|
|
}
|
|
|
String redisValue = null;
|
|
|
|
|
|
if (value instanceof String) {
|
|
|
redisValue = (String) value;
|
|
|
} else {
|
|
|
redisValue = JSON.toJSONString(value);
|
|
|
}
|
|
|
try {
|
|
|
getZsetOperations().add(key, redisValue, score);
|
|
|
} catch (Exception e) {
|
|
|
warnLogger.warn("add sortedSet cache failed!!! cachekey is " + key + "value is " + value, e);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @param key
|
|
|
* @param value
|
|
|
*/
|
|
|
public void setIfAbsent(String key, Object value) {
|
|
|
if (isCache()) {
|
|
|
return;
|
|
|
}
|
|
|
String redisValue = null;
|
|
|
|
|
|
if (value instanceof String) {
|
|
|
redisValue = (String) value;
|
|
|
} else {
|
|
|
redisValue = JSON.toJSONString(value);
|
|
|
}
|
|
|
try {
|
|
|
getValueOperations().setIfAbsent(key, redisValue);
|
|
|
} catch (Exception e) {
|
|
|
warnLogger.warn("add cache failed!!! cachekey is:{}", key, e);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @param key
|
|
|
* @param clazz
|
|
|
* @return
|
|
|
*/
|
|
|
public <T> List<T> getList(String key, Class<T> clazz) {
|
|
|
if (isCache()) {
|
|
|
return null;
|
|
|
}
|
|
|
List<T> t = null;
|
|
|
try {
|
|
|
String value = getValueOperations().get(key);
|
|
|
if (StringUtils.isBlank(value)) {
|
|
|
logger.info("cache miss key is:{}", key);
|
|
|
return null;
|
|
|
}
|
|
|
t = JSON.parseArray(value, clazz);
|
|
|
logger.info("cache hit key is:{}", key);
|
|
|
return t;
|
|
|
} catch (Exception e) {
|
|
|
warnLogger.warn("get from cache failed!!! key is:{}", key, e);
|
|
|
return null;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* redis list 获取值列表, 全部记录
|
|
|
*
|
|
|
* @param key
|
|
|
* @param length
|
|
|
* @param startIndex
|
|
|
* @param clazz
|
|
|
* @return
|
|
|
*/
|
|
|
public List<String> getValueList(String key, int startIndex, int endIndex) {
|
|
|
if (isCache()) {
|
|
|
return Lists.newArrayList();
|
|
|
}
|
|
|
try {
|
|
|
List<String> valueList = getListOperations().range(key, startIndex, endIndex);
|
|
|
|
|
|
if (CollectionUtils.isEmpty(valueList)) {
|
|
|
logger.info("cache miss key is:{}", key);
|
|
|
return Lists.newArrayList();
|
|
|
}
|
|
|
logger.info("cache hit key is:{}", key);
|
|
|
return valueList;
|
|
|
} catch (Exception e) {
|
|
|
warnLogger.warn("get from cache failed!!! key is:{}", key, e);
|
|
|
return Lists.newArrayList();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* redis list 设置, 左塞
|
|
|
*
|
|
|
* @param key
|
|
|
* @param clazz
|
|
|
* @return
|
|
|
*/
|
|
|
public void leftSetValueList(String key, String value) {
|
|
|
if (isCache()) {
|
|
|
return;
|
|
|
}
|
|
|
try {
|
|
|
getListOperations().leftPush(key, value);
|
|
|
} catch (Exception e) {
|
|
|
warnLogger.warn("set cache failed!!! key is: {},value is:{}", key, value, e);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* redis list 设置, 左塞 (批量接口)
|
|
|
*
|
|
|
* @param key
|
|
|
* @param clazz
|
|
|
* @return
|
|
|
*/
|
|
|
public void batchLeftSetValueList(String key, List<String> values) {
|
|
|
if (isCache()) {
|
|
|
return;
|
|
|
}
|
|
|
if (CollectionUtils.isEmpty(values)) {
|
|
|
return;
|
|
|
}
|
|
|
try {
|
|
|
getListOperations().leftPushAll(key, values);
|
|
|
} catch (Exception e) {
|
|
|
warnLogger.warn("batchLeftSetValueList cache failed!!! key is:{} ,values is:{}", key, values, e);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
*
|
|
|
* @param key
|
|
|
* @param value
|
|
|
* object
|
|
|
*/
|
|
|
|
|
|
public void leftSetObjectValueList(String key, Object value) {
|
|
|
if (isCache()) {
|
|
|
return;
|
|
|
}
|
|
|
try {
|
|
|
getListOperations().leftPush(key, JSON.toJSONString(value));
|
|
|
} catch (Exception e) {
|
|
|
warnLogger.warn("set cache failed!!! key is:{},value is:{} ", key, value, e);
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
*
|
|
|
* @param key
|
|
|
* @param values
|
|
|
*/
|
|
|
public void batchLeftSetObjectValueList(String key, List<? extends Object> values) {
|
|
|
if (isCache()) {
|
|
|
return;
|
|
|
}
|
|
|
if (CollectionUtils.isEmpty(values)) {
|
|
|
return;
|
|
|
}
|
|
|
List<String> jsonValues = Lists.newArrayList();
|
|
|
for (Object object : values) {
|
|
|
jsonValues.add(JSON.toJSONString(object));
|
|
|
}
|
|
|
try {
|
|
|
getListOperations().leftPushAll(key, jsonValues);
|
|
|
} catch (Exception e) {
|
|
|
warnLogger.warn("set cache failed!!! key is:{} ", key, e);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
*
|
|
|
* @param key
|
|
|
* @param values
|
|
|
*/
|
|
|
public void batchRightSetObjectValueList(String key, List<? extends Object> values) {
|
|
|
if (isCache()) {
|
|
|
return;
|
|
|
}
|
|
|
if (CollectionUtils.isEmpty(values)) {
|
|
|
return;
|
|
|
}
|
|
|
List<String> jsonValues = Lists.newArrayList();
|
|
|
for (Object object : values) {
|
|
|
jsonValues.add(JSON.toJSONString(object));
|
|
|
}
|
|
|
try {
|
|
|
getListOperations().rightPushAll(key, jsonValues);
|
|
|
} catch (Exception e) {
|
|
|
warnLogger.warn("set cache failed!!! key is:{} ", key, e);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* redis list 设置, 右塞 (批量接口)
|
|
|
*
|
|
|
* @param key
|
|
|
* @param clazz
|
|
|
* @return
|
|
|
*/
|
|
|
public void batchRightSetValueList(String key, List<String> values) {
|
|
|
if (isCache()) {
|
|
|
return;
|
|
|
}
|
|
|
if (CollectionUtils.isEmpty(values)) {
|
|
|
return;
|
|
|
}
|
|
|
try {
|
|
|
getListOperations().rightPushAll(key, values);
|
|
|
} catch (Exception e) {
|
|
|
warnLogger.warn("batchLeftSetValueList cache failed!!! key is:{} ", key, e);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @param key
|
|
|
* @param startIndex
|
|
|
* @param length
|
|
|
* @param clazz
|
|
|
* @return
|
|
|
*/
|
|
|
public <T> List<T> getValueObjectList(String key, int startIndex, int length, Class<T> clazz) {
|
|
|
if (isCache()) {
|
|
|
return Lists.newArrayList();
|
|
|
}
|
|
|
try {
|
|
|
|
|
|
List<String> valueList = getListOperations().range(key, startIndex, length);
|
|
|
if (CollectionUtils.isEmpty(valueList)) {
|
|
|
logger.info("cache miss key is:{}", key);
|
|
|
return Lists.newArrayList();
|
|
|
}
|
|
|
logger.info("cache hit key is:{}", key);
|
|
|
List<T> list = Lists.newArrayList();
|
|
|
for (String value : valueList) {
|
|
|
T t = JSON.parseObject(value, clazz);
|
|
|
if (null != t) {
|
|
|
list.add(t);
|
|
|
}
|
|
|
}
|
|
|
return list;
|
|
|
} catch (Exception e) {
|
|
|
warnLogger.warn("get from cache failed!!! key is:{}", key, e);
|
|
|
return Lists.newArrayList();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @param key
|
|
|
* @return
|
|
|
*/
|
|
|
public String getString(String key) {
|
|
|
if (isCache()) {
|
|
|
return null;
|
|
|
}
|
|
|
String value = null;
|
|
|
try {
|
|
|
value = getValueOperations().get(key);
|
|
|
if (StringUtils.isBlank(value)) {
|
|
|
logger.info("cache miss key is:{}", key);
|
|
|
} else {
|
|
|
logger.info("cache hit key is:{}", key);
|
|
|
}
|
|
|
return value;
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
warnLogger.warn("get from cache failed!!! key is:{}", key, e);
|
|
|
return null;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public Long incr(String key, long delta) {
|
|
|
if (isCache()) {
|
|
|
return null;
|
|
|
}
|
|
|
try {
|
|
|
return getValueOperations().increment(key, delta);
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
warnLogger.warn("incr failed!!! key is:{}", key, e);
|
|
|
return null;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @param key
|
|
|
* @param clazz
|
|
|
* @return
|
|
|
*/
|
|
|
public <T> T get(String key, Class<T> clazz) {
|
|
|
if (isCache()) {
|
|
|
return null;
|
|
|
}
|
|
|
T t = null;
|
|
|
try {
|
|
|
String value = getValueOperations().get(key);
|
|
|
|
|
|
if (StringUtils.isBlank(value)) {
|
|
|
logger.info("cache miss key is:{}", key);
|
|
|
return null;
|
|
|
}
|
|
|
t = getValue(value, clazz);
|
|
|
logger.info("cache hit key is:{}", key);
|
|
|
return t;
|
|
|
} catch (Exception e) {
|
|
|
warnLogger.warn("get from cache failed!!! key is:{}", key, e);
|
|
|
return null;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @param keys
|
|
|
*/
|
|
|
public void delete(Collection<String> keys) {
|
|
|
if (isCache() || CollectionUtils.isEmpty(keys)) {
|
|
|
return;
|
|
|
}
|
|
|
try {
|
|
|
getRedisTemplate().delete(keys);
|
|
|
} catch (Exception e) {
|
|
|
warnLogger.warn("delete from cache failed!!! key is:{}", keys, e);
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
public void evictFromList(String key, String value, long count) {
|
|
|
if (isCache()) {
|
|
|
return;
|
|
|
}
|
|
|
try {
|
|
|
getListOperations().remove(key, count, value);
|
|
|
} catch (Exception e) {
|
|
|
warnLogger.warn("remove cache failed!!! key is: " + key + "; value = " + value, e);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 查询某键值对应list列表的长度
|
|
|
*
|
|
|
* @param level
|
|
|
* @param name
|
|
|
* @param key
|
|
|
* @return
|
|
|
*/
|
|
|
public long getValueListCount(String key) {
|
|
|
if (isCache()) {
|
|
|
return 0;
|
|
|
}
|
|
|
try {
|
|
|
Long size = getListOperations().size(key);
|
|
|
if (null == size) {
|
|
|
return 0;
|
|
|
} else {
|
|
|
return size;
|
|
|
}
|
|
|
} catch (Exception e) {
|
|
|
warnLogger.warn("getValueListCount cache failed!!! key is:{} ", key, e);
|
|
|
return 0;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 批量插入sortSet元素,只支持同一键值
|
|
|
*
|
|
|
* @param valueAndScoreMap
|
|
|
* 键值为存储的值,map值为当前值的score(用于排序) 默认是升序
|
|
|
*/
|
|
|
public void msetSortSet(String key, Map<Object, Double> valueAndScoreMap) {
|
|
|
if (isCache() || MapUtils.isEmpty(valueAndScoreMap)) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
Set<TypedTuple<String>> typedTuples = new HashSet<TypedTuple<String>>(valueAndScoreMap.size());
|
|
|
Object curValue;
|
|
|
for (Entry<Object, Double> entry : valueAndScoreMap.entrySet()) {
|
|
|
final String curValueStr;
|
|
|
curValue = entry.getKey();
|
|
|
if (curValue instanceof String) {
|
|
|
curValueStr = (String) curValue;
|
|
|
} else {
|
|
|
curValueStr = JSON.toJSONString(curValue);
|
|
|
}
|
|
|
|
|
|
typedTuples.add(new TypedTuple<String>() {
|
|
|
@Override
|
|
|
public int compareTo(TypedTuple<String> o) {
|
|
|
return this.getScore() >= o.getScore() ? 1 : -1;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public String getValue() {
|
|
|
return curValueStr;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public Double getScore() {
|
|
|
return entry.getValue();
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
getZsetOperations().add(key, typedTuples);
|
|
|
} catch (Exception e) {
|
|
|
warnLogger.warn("add zSetOperations cache failed!!! map key is" + key + "; valueAndScoreMap is " + valueAndScoreMap, e);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 查询sortedSet的长度
|
|
|
*/
|
|
|
public Long countSortSet(String key) {
|
|
|
if (isCache()) {
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
return getZsetOperations().size(key);
|
|
|
} catch (Exception e) {
|
|
|
warnLogger.warn("count zSetOperations cache failed!!! key is" + key, e);
|
|
|
}
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 查询sortedSet的长度
|
|
|
*/
|
|
|
public Long removeSortSet(String key, Object... values) {
|
|
|
if (isCache() || null == values || 0 == values.length) {
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
return getZsetOperations().remove(key, values);
|
|
|
} catch (Exception e) {
|
|
|
warnLogger.warn("remove zSetOperations cache failed!!! key is" + key + "; values is " + values, e);
|
|
|
}
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 分页查询sortedSet 查询失败则返回空的set
|
|
|
*/
|
|
|
public Set<String> rangeSortSet(String key, long start, long end) {
|
|
|
if (isCache()) {
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
return getZsetOperations().reverseRange(key, start, end);
|
|
|
} catch (Exception e) {
|
|
|
warnLogger.warn("range zSetOperations cache failed!!! key is" + key + "; start is " + start + "; end is " + end, e);
|
|
|
}
|
|
|
return new HashSet<String>(0);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 查询sortSet中有无当前的值 是否在set已有
|
|
|
*/
|
|
|
public boolean existSortSet(String key, Object value) {
|
|
|
if (isCache()) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
return null != getZsetOperations().score(key, value);
|
|
|
} catch (Exception e) {
|
|
|
warnLogger.warn("score zSetOperations cache failed!!! key is" + key + "; value is " + value, e);
|
|
|
}
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
@SuppressWarnings("unchecked")
|
|
|
private <T> T getValue(String value, Class<T> clazz) {
|
|
|
T t = null;
|
|
|
if (clazz.equals(String.class)) {
|
|
|
t = (T) value;
|
|
|
} else if (clazz.equals(Integer.class)) {
|
|
|
t = (T) Integer.valueOf(value);
|
|
|
} else {
|
|
|
try{
|
|
|
t = JSON.parseObject(value, clazz);
|
|
|
}catch (Exception e) {
|
|
|
warnLogger.warn("get value cache failed!!! value is: "+ value,e);
|
|
|
}
|
|
|
}
|
|
|
return t;
|
|
|
}
|
|
|
|
|
|
|
|
|
public <T> Map<String, T> pipelineGet(List<String> keys, Class<T> clazz){
|
|
|
if (isCache()||CollectionUtils.isEmpty(keys)) {
|
|
|
return null;
|
|
|
}
|
|
|
long beginTime = System.currentTimeMillis();
|
|
|
Map<String, T> result = new HashMap<String, T>(keys.size());
|
|
|
try {
|
|
|
List<Object> values=getRedisTemplate().executePipelined(new RedisCallback<Object>() {
|
|
|
@Override
|
|
|
public Object doInRedis(RedisConnection connection) throws DataAccessException {
|
|
|
connection.openPipeline();
|
|
|
for (String key : keys) {
|
|
|
connection.get(key.getBytes(CHARSET_UTF_8));
|
|
|
}
|
|
|
// 无需返回是否缓存成功
|
|
|
return null;
|
|
|
}
|
|
|
});
|
|
|
int index=0;
|
|
|
for (Object redisBack : values) {
|
|
|
if (null != redisBack) {
|
|
|
result.put(keys.get(index),getValue((String)redisBack, clazz));
|
|
|
}else{
|
|
|
result.put(keys.get(index),null);
|
|
|
}
|
|
|
index++;
|
|
|
}
|
|
|
return result;
|
|
|
} catch (Exception e) {
|
|
|
warnLogger.warn("get from cache failed!!! keys is: {}", keys, e);
|
|
|
HashMap<String, T> hashMap = new HashMap<String, T>(keys.size());
|
|
|
for (String key : keys) {
|
|
|
hashMap.put(key, null);
|
|
|
}
|
|
|
return hashMap;
|
|
|
}finally {
|
|
|
long endTime = System.currentTimeMillis();
|
|
|
long costTime = endTime - beginTime;
|
|
|
if (costTime > TIMEOUT_THRESHOLD) {
|
|
|
redisTimeOutLogger.warn("get from cache timeout!!! keys size is:{} cost time:{}", keys.size(), costTime);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
} |
...
|
...
|
|