一、pom依赖
<dependency>
<groupId>tf56.redis</groupId>
<artifactId>redis-client</artifactId>
<version>1.0.0</version>
<exclusions>
<exclusion>
<artifactId>servlet-api</artifactId>
<groupId>javax.servlet</groupId>
</exclusion>
<exclusion>
<artifactId>gson</artifactId>
<groupId>com.google.code.gson</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- 其他redis依赖 -->
二、MyCacheCloudRedisFactory工具类
package tf56.payOnlineService.util.redis;
import com.sohu.tv.builder.ClientBuilder;
import com.sohu.tv.cachecloud.client.basic.enums.RedisTypeEnum;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisSentinelPool;
import redis.clients.jedis.ScanParams;
import redis.clients.jedis.ScanResult;
import redis.clients.jedis.Transaction;
import tf56.common.redis.model.CommonConfigProp;
import tf56.common.util.PropUtil;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
/**
* CacheCloud Redis 云工厂
* Created by Trying on 2017/4/10 16:46.
*/
public class MyCacheCloudRedisFactory {
protected static final Logger log = LoggerFactory.getLogger(MyCacheCloudRedisFactory.class);
/** 默认资源文件路径 */
public static final String DEFAULT_PROP_FILEPATH = "config/CacheCloud.properties";
/** 默认失效时间,单位:秒 */
private static final int DEFAULT_EXPIRE_SECOND = 60;
/** Jedis sentinel 连接池 */
JedisSentinelPool jedisSentinelPool = null;
private static final Long RELEASE_SUCCESS = 1L;
private static final String LOCK_SUCCESS = "OK";
/**
* 默认构造函数,会自动从默认配置文件 ["config/CacheCloud.properties"] 读取必要参数
*/
public MyCacheCloudRedisFactory() throws Exception {
this.initWithProp(null, null);
}
/**
* 指定资源文件路径的构造函数。具体参数的key沿用默认的。
* @param propFilepath 资源文件路径
* @throws Exception 异常时,无法构造实例
*/
public MyCacheCloudRedisFactory(String propFilepath) throws Exception {
this.initWithProp(propFilepath, null);
}
/**
* 使用默认的资源文件路径
* @param configProp 资源文件配置
* @throws Exception 异常时,无法构造实例
*/
public MyCacheCloudRedisFactory(CommonConfigProp configProp) throws Exception {
this.initWithProp(null, configProp);
}
/**
* 指定资源文件路径、资源文件配置信息
* @param propFilepath 资源文件路径
* @param configProp 资源文件配置
* @throws Exception 异常时,无法构造实例
*/
public MyCacheCloudRedisFactory(String propFilepath, CommonConfigProp configProp) throws Exception {
this.initWithProp(propFilepath, configProp);
}
/**
* 个性化构造函数
* @param redisTypeEnum Redis类型,非null
* @param cacheCloudAppId CacheCloud应用中的appId,非null,大于0的long型数据
*/
public MyCacheCloudRedisFactory(RedisTypeEnum redisTypeEnum, Long cacheCloudAppId, String appKey) throws Exception {
this.init(redisTypeEnum, cacheCloudAppId, appKey, null);
}
private void initWithProp(String propFilepath, CommonConfigProp configProp) throws Exception {
if (propFilepath==null || propFilepath.trim().length()==0) {
propFilepath = DEFAULT_PROP_FILEPATH;
}
if (configProp==null) {
configProp = new CommonConfigProp();
}
String redisTypeKey = configProp.concatPrefixAndSuffix(configProp.getRedisTypeKey());
String redisType = PropUtil.getPropValue(propFilepath, redisTypeKey, null);
String appIdKey = configProp.concatPrefixAndSuffix(configProp.getAppIdKey());
String appIdStr = PropUtil.getPropValue(propFilepath, appIdKey, null);
String appKeyKey = configProp.concatPrefixAndSuffix(configProp.getAppKeyKey());
String appkeyStr = PropUtil.getPropValue(propFilepath, appKeyKey, null);
RedisTypeEnum redisTypeEnum = null;
long appId = 0;
try {
if (redisType==null || redisType.trim().length()==0) {
redisTypeEnum = RedisTypeEnum.SENTINEL;
} else {
redisTypeEnum = RedisTypeEnum.valueOf(redisType);
}
appId = Long.parseLong(appIdStr);
} catch (Exception e) {
String msg = propFilepath + "{"+redisTypeKey + ":" + redisType + ", " + appIdKey + ":" + appIdStr + "}. \n";
log.warn(msg + e.getMessage());
throw new Exception(msg);
}
if (StringUtils.isBlank(appkeyStr)) {
String msg = propFilepath + "{"+appKeyKey + ":" + appkeyStr +"}. \n Invalid param appKey !";
log.warn(msg);
throw new Exception(msg);
}
/* 连接池配置 */
GenericObjectPoolConfig poolConfig = null;
try {
String minIdleKey = configProp.concatPrefixAndSuffix(configProp.getPoolMinIdleKey());
String minIdleStr = PropUtil.getPropValue(propFilepath, minIdleKey, null);
String maxIdleKey = configProp.concatPrefixAndSuffix(configProp.getPoolMaxIdleKey());
String maxIdleStr = PropUtil.getPropValue(propFilepath, maxIdleKey, null);
String maxTotalKey = configProp.concatPrefixAndSuffix(configProp.getPoolMaxTotalKey());
String maxTotalStr = PropUtil.getPropValue(propFilepath, maxTotalKey, null);
int minIdle = 0;
int maxIdle = 0;
int maxTotal = 0;
if (minIdleStr != null)
minIdle = Integer.parseInt(minIdleStr);
if (maxIdleStr != null)
maxIdle = Integer.parseInt(maxIdleStr);
if (maxTotalStr != null)
maxTotal = Integer.parseInt(maxTotalStr);
poolConfig = new GenericObjectPoolConfig();
if (minIdle>0) {
poolConfig.setMinIdle(minIdle);
}
if (maxIdle>0 && maxIdle>minIdle) {
poolConfig.setMaxIdle(maxIdle);
}
if (maxTotal>0) {
poolConfig.setMaxTotal(maxTotal);
}
} catch (Exception e) {
String msg = "Read pool config ERROR!";
log.warn(msg, e); // 连接池配置信息读取异常时,将只记录日志警告,并使用默认配置。而不抛异常。
}
this.init(redisTypeEnum, appId, appkeyStr, poolConfig);
}
/**
* 初始化
* @param redisTypeEnum Redis类型,非null
* @param cacheCloudAppId CacheCloud应用中的appId,非null,大于0的long型数据
*/
private void init(RedisTypeEnum redisTypeEnum, Long cacheCloudAppId, String appKey, GenericObjectPoolConfig poolConfig) throws Exception {
if (redisTypeEnum==null || (cacheCloudAppId==null || cacheCloudAppId<=0)) {
String msg = "Invalid input params:{redisTypeEnum:"+redisTypeEnum + ", cacheCloudAppId:"+cacheCloudAppId;
log.warn(msg);
throw new Exception(msg);
}
if (poolConfig==null) { // 默认连接池配置
poolConfig = new GenericObjectPoolConfig();
poolConfig.setMinIdle(100);
poolConfig.setMaxIdle(1000);
poolConfig.setMaxTotal(10000);
}
switch (redisTypeEnum) {
case SENTINEL:
default:
jedisSentinelPool = this.buildJedisSentinelPool(cacheCloudAppId, appKey, poolConfig);
}
}
/**
* 构建 jedis 的 sentinel 连接池
* @param cacheCloudAppId CacheCloud 平台中的应用ID
* @param poolConfig jedis连接池设置
* @return 连接池
*/
private JedisSentinelPool buildJedisSentinelPool(Long cacheCloudAppId, String appkey, GenericObjectPoolConfig poolConfig) {
if (cacheCloudAppId==null || cacheCloudAppId<=0) {
return null;
}
if (poolConfig==null) {
poolConfig = new GenericObjectPoolConfig();
}
return ClientBuilder.redisSentinel(cacheCloudAppId)
.setConnectionTimeout(1000)
.setSoTimeout(1000)
.setPoolConfig(poolConfig)
.buildWithSafeCheck(true, appkey);
}
/**
* 测试服务器是否正常
*
* @return 正常情况下,返回:PONG
*/
public String ping() {
if (jedisSentinelPool==null) {
log.warn("jedisSentinelPool is null !");
return null;
}
Jedis jedis = null;
try {
jedis = jedisSentinelPool.getResource();
return jedis.ping();
} catch (Exception e) {
log.error("Redis get ERROR!", e);
} finally {
if(jedis!=null) {
jedis.close();
}
}
return null;
}
/**
* 对 key 增加 1
*
* @param key 键
* @return 执行结果
*/
public Long incr(final String key) {
if (jedisSentinelPool==null) {
log.warn("jedisSentinelPool is null !");
return null;
}
if (key==null) {
log.warn("Key is null !");
return null;
}
Jedis jedis = null;
try {
jedis = jedisSentinelPool.getResource();
return jedis.incr(key);
} catch (Exception e) {
log.error("Redis incr ERROR!", e);
} finally {
if(jedis!=null) {
jedis.close();
}
}
return null;
}
/**
* 对 key 增加 number。(如果number为负数,则为减少)
*
* @param key 键
* @param number 长整形增量
* @return 执行结果
*/
public Long incrByLong(final String key, final Long number) {
if (jedisSentinelPool==null) {
log.warn("jedisSentinelPool is null !");
return -1L;
}
if (key==null || number==null) {
log.warn("Key or number is null !");
return -1L;
}
Jedis jedis = null;
try {
jedis = jedisSentinelPool.getResource();
return jedis.incrBy(key, number);
} catch (Exception e) {
log.error("Redis incrBy ERROR!", e);
} finally {
if(jedis!=null) {
jedis.close();
}
}
return -1L;
}
/**
* 对 key 增加 number。(如果number为负数,则为减少)
*
* @param key 键
* @param number 浮点型增量
* @return 执行结果
*/
public Double incrByDouble(final String key, final Double number) {
if (jedisSentinelPool==null) {
log.warn("jedisSentinelPool is null !");
return null;
}
if (key==null || number==null) {
log.warn("Key or number is null !");
return null;
}
Jedis jedis = null;
try {
jedis = jedisSentinelPool.getResource();
return jedis.incrByFloat(key, number);
} catch (Exception e) {
log.error("Redis incrByFloat ERROR!", e);
} finally {
if(jedis!=null) {
jedis.close();
}
}
return null;
}
private long parseLong(String data) {
long rst = 0;
try {
rst = Long.parseLong(data);
} catch (Exception e) {
log.error("Trying ERROR!", e);
}
return rst;
}
/**
* 设置字符串缓存,使用默认存活时长60秒
* 此方法实现有bug,失效时间可能不会起作用
* @param key 键
* @param value 值
*/
public void set(String key, String value) {
this.set(key, value, DEFAULT_EXPIRE_SECOND);
}
/**
* 设置缓存,并指定过期时间
* @param key
* @param value
* @param second 最大48小时
*/
public void setEx(final String key,final String value,int second) {
if (second > 48 * 3600) {
second = 48 * 3600;
}
Jedis jedis = this.getJedisConnection();
jedis.setex(key, second, value);
}
/**
* 验证缓存的key 是否存在
* @param key
* @return
*/
public Boolean exists(String key) {
if (key == null || key.equals("")) {
return Boolean.FALSE;
}
return this.jedisSentinelPool.getResource().exists(key);
}
/**
* 设置字符串缓存
*
* @param key 键
* @param value 值
* @param liveTime 存活时长,单位:秒。如果持久化保存,就设置为-1
*/
public void set(String key, String value, int liveTime) {
if (jedisSentinelPool==null) {
log.warn("jedisSentinelPool is null !");
return;
}
if (key==null || value == null) {
log.warn("Key or Value is null :key="+key+"---------value="+value);
return;
}
Jedis jedis = null;
try {
jedis = jedisSentinelPool.getResource();
jedis.set(key, value);
if (liveTime>0) {
jedis.expire(key, liveTime);
}
} catch (Exception e) {
log.error("Redis set ERROR!", e);
} finally {
if(jedis!=null)
jedis.close();
}
}
/**
* 设置指定key的存活时长。<br/>
* 一般用于再次延长key的存活时长。
*
* @param key 键
* @param liveTime 存活时长,单位:秒。如果持久化保存,就设置为-1
*/
public void expire(String key, int liveTime) {
if (jedisSentinelPool==null) {
log.warn("jedisSentinelPool is null !");
return;
}
if (key==null || liveTime<=0) {
log.warn("Key or Value is null :key="+key+", liveTime="+liveTime);
return;
}
Jedis jedis = null;
try {
jedis = jedisSentinelPool.getResource();
jedis.expire(key, liveTime);
} catch (Exception e) {
log.error("Redis set ERROR!", e);
} finally {
if(jedis!=null)
jedis.close();
}
}
/**
* 读取字符串缓存
*
* @param key 键
* @return 缓存的字符串值
*/
public String get(final String key) {
if (jedisSentinelPool==null) {
log.warn("jedisSentinelPool is null !");
return null;
}
if (key==null) {
log.warn("Key is null !");
return null;
}
Jedis jedis = null;
try {
jedis = jedisSentinelPool.getResource();
return jedis.get(key);
} catch (Exception e) {
log.error("Redis get ERROR!", e);
} finally {
if(jedis!=null) {
jedis.close();
}
}
return null;
}
/**
* 删除指定的缓存key
*
* @param keys 待删除的key
* @return 执行结果
*/
public long del(final String... keys) {
if (jedisSentinelPool==null) {
log.warn("jedisSentinelPool is null !");
return 0;
}
if (keys==null || keys.length==0) {
log.warn("Keys is null !");
return 0;
}
long rst = 0;
Jedis jedis = null;
try {
jedis = jedisSentinelPool.getResource();
rst = jedis.del(keys);
} catch (Exception e) {
log.error("Redis get ERROR!", e);
} finally {
if(jedis!=null) {
jedis.close();
}
}
return rst;
}
/**
* hash 类型的 redis 数据缓存。默认存活60秒。
* @param key redis 的缓存 key
* @param field 缓存的 hash 数据的字段名
* @param value 缓存的 hash 数据的字段值
*/
public void hset(String key, String field, String value) {
this.hset(key, field, value, DEFAULT_EXPIRE_SECOND);
}
/**
* hash 类型的 redis 数据缓存
* @param key redis 的缓存 key
* @param field 缓存的 hash 数据的字段名
* @param value 缓存的 hash 数据的字段值
* @param liveTime 存活时长,秒
*/
public void hset(String key, String field, String value, int liveTime) {
if (jedisSentinelPool==null) {
log.warn("jedisSentinelPool is null !");
return;
}
if (key==null || field==null || value == null) {
log.warn("Input param is null :key="+key+", field="+field+", value="+value);
return;
}
Jedis jedis = null;
try {
jedis = jedisSentinelPool.getResource();
jedis.hset(key, field, value);
if (liveTime>0) {
jedis.expire(key, liveTime);
}
} catch (Exception e) {
log.error("Redis hset ERROR!", e);
} finally {
if(jedis!=null)
jedis.close();
}
}
/**
* 读取hash缓存
*
* @param key 键
* @return hash数据属性值
*/
public String hget(final String key, final String field) {
if (jedisSentinelPool==null) {
log.warn("jedisSentinelPool is null !");
return null;
}
if (key==null) {
log.warn("Key is null !");
return null;
}
Jedis jedis = null;
try {
jedis = jedisSentinelPool.getResource();
return jedis.hget(key, field);
} catch (Exception e) {
log.error("Redis hget ERROR!", e);
} finally {
if(jedis!=null) {
jedis.close();
}
}
return null;
}
/**
* hash 类型的 redis 数据缓存。同时缓存多个属性。批量缓存。
* 默认存活60秒。
*
* @param key redis 的缓存 key
* @param hash 缓存的 hash 数据。字段名:字段值
*/
public void hmset(String key, Map<String, String> hash) {
this.hmset(key, hash, DEFAULT_EXPIRE_SECOND);
}
/**
* hash 类型的 redis 数据缓存。同时缓存多个属性。批量缓存。
*
* @param key redis 的缓存 key
* @param hash 缓存的 hash 数据。字段名:字段值
* @param liveTime 存活时长,秒
*/
public void hmset(String key, Map<String, String> hash, int liveTime) {
if (jedisSentinelPool==null) {
log.warn("jedisSentinelPool is null !");
return;
}
if (key==null || hash == null || hash.size()==0) {
log.warn("Input param is null :key="+key+", hash="+hash);
return;
}
Jedis jedis = null;
try {
jedis = jedisSentinelPool.getResource();
jedis.hmset(key, hash);
if (liveTime>0) {
jedis.expire(key, liveTime);
}
} catch (Exception e) {
log.error("Redis hmset ERROR!", e);
} finally {
if(jedis!=null)
jedis.close();
}
}
/**
* 批量读取hash缓存指定的属性值
*
* @param key 键
* @param field hash数据的属性数组。
* @return hash数据的属性值列表。
*/
public List<String> hmget(final String key, final String... field) {
if (jedisSentinelPool==null) {
log.warn("jedisSentinelPool is null !");
return null;
}
if (key==null || field==null) {
log.warn("Key or field is null !");
return null;
}
Jedis jedis = null;
try {
jedis = jedisSentinelPool.getResource();
return jedis.hmget(key, field);
} catch (Exception e) {
log.error("Redis hmget ERROR!", e);
} finally {
if(jedis!=null) {
jedis.close();
}
}
return null;
}
/**
* 批量读取hash缓存
*
* @param key 键
* @return hash数据的值。
*/
public Map<String, String> hgetAll(final String key) {
if (jedisSentinelPool==null) {
log.warn("jedisSentinelPool is null !");
return null;
}
if (key==null) {
log.warn("Key is null !");
return null;
}
Jedis jedis = null;
try {
jedis = jedisSentinelPool.getResource();
return jedis.hgetAll(key);
} catch (Exception e) {
log.error("Redis hgetAll ERROR!", e);
} finally {
if(jedis!=null) {
jedis.close();
}
}
return null;
}
/**
* 批量读取hash缓存
*
* @param key 键
* @return hash数据的值。
*/
public void hdel(String key, String... field) {
if (jedisSentinelPool==null) {
log.warn("jedisSentinelPool is null !");
return;
}
if (key==null || field==null) {
log.warn("Key or field is null !");
return;
}
Jedis jedis = null;
try {
jedis = jedisSentinelPool.getResource();
jedis.hdel(key, field);
} catch (Exception e) {
log.error("Redis hdel ERROR!", e);
} finally {
if(jedis!=null) {
jedis.close();
}
}
}
/**
* hash 扫描 。
* 注意:原 scanHashs 方法的调用,返回的类型是spring-dto-bean包中的,这里需要切换!!!
*
* @param key 指定 hash 的 key
* @param pattern 正则
* @param count 统计量
* @return 扫描结果
*/
public ScanResult<Map.Entry<String, String>> hscan(String key, String pattern, Integer count) {
if (jedisSentinelPool==null) {
log.warn("jedisSentinelPool is null !");
return null;
}
if (key==null) {
log.warn("Key is null !");
return null;
}
ScanResult<Map.Entry<String, String>> scanResult = null;
Jedis jedis = null;
try {
jedis = jedisSentinelPool.getResource();
ScanParams scanParams = null;
if (pattern!=null || count!=null) {
scanParams = new ScanParams();
}
if (count!=null) {
scanParams.count(count);
}
if (pattern!=null) {
scanParams.match(pattern);
}
if (scanParams!=null) {
scanResult = jedis.hscan(key, ScanParams.SCAN_POINTER_START, scanParams);
} else {
scanResult = jedis.hscan(key, ScanParams.SCAN_POINTER_START);
}
} catch (Exception e) {
log.error("Redis hscan ERROR!", e);
} finally {
if(jedis!=null)
jedis.close();
}
return scanResult;
}
/**
* 集合添加元素
*
* @param key 集合的key
* @param members 待添加的集合中的元素
* @return 执行结果
*/
public Long sadd(final String key, final String... members) {
if (jedisSentinelPool==null) {
log.warn("jedisSentinelPool is null !");
return null;
}
if (key==null || members==null || members.length==0) {
log.warn("Key or members is null !");
return null;
}
Jedis jedis = null;
try {
jedis = jedisSentinelPool.getResource();
return jedis.sadd(key, members);
} catch (Exception e) {
log.error("Redis sadd ERROR!", e);
} finally {
if(jedis!=null)
jedis.close();
}
return null;
}
/**
* 统计集合中元素数
*
* @param key 集合的key
* @return 执行结果
*/
public Long scard(final String key) {
if (jedisSentinelPool==null) {
log.warn("jedisSentinelPool is null !");
return null;
}
if (key==null) {
log.warn("Key is null !");
return null;
}
Jedis jedis = null;
try {
jedis = jedisSentinelPool.getResource();
return jedis.scard(key);
} catch (Exception e) {
log.error("Redis scard ERROR!", e);
} finally {
if(jedis!=null)
jedis.close();
}
return null;
}
/**
* 查询集合中的元素
*
* @param key 集合的key
* @return 集合元素
*/
public Set<String> smembers(final String key) {
if (jedisSentinelPool==null) {
log.warn("jedisSentinelPool is null !");
return null;
}
if (key==null) {
log.warn("Key is null !");
return null;
}
Jedis jedis = null;
try {
jedis = jedisSentinelPool.getResource();
return jedis.smembers(key);
} catch (Exception e) {
log.error("Redis smembers ERROR!", e);
} finally {
if(jedis!=null)
jedis.close();
}
return null;
}
/**
* 从队列左侧推入
*
* @param key 队列的key
* @param values 待推入的队列元素值
* @return 执行结果
*/
public Long lpush(final String key,final String... values) {
if (jedisSentinelPool==null) {
log.warn("jedisSentinelPool is null !");
return null;
}
if (key==null || values==null) {
log.warn("Key or values is null !");
return null;
}
Jedis jedis = null;
try {
jedis = jedisSentinelPool.getResource();
return jedis.lpush(key, values);
} catch (Exception e) {
log.error("Redis lpush ERROR!", e);
} finally {
if(jedis!=null)
jedis.close();
}
return null;
}
/**
* 从队列左侧弹出
*
* @param key 队列的key
* @return 弹出的元素
*/
public String lpop(final String key) {
if (jedisSentinelPool==null) {
log.warn("jedisSentinelPool is null !");
return null;
}
if (key==null) {
log.warn("Key is null !");
return null;
}
Jedis jedis = null;
try {
jedis = jedisSentinelPool.getResource();
return jedis.lpop(key);
} catch (Exception e) {
log.error("Redis lpop ERROR!", e);
} finally {
if(jedis!=null)
jedis.close();
}
return null;
}
/**
* 从队列右侧弹出
*
* @param key 队列的key
* @return 弹出的元素
*/
public String rpop(final String key) {
if (jedisSentinelPool==null) {
log.warn("jedisSentinelPool is null !");
return null;
}
if (key==null) {
log.warn("Key is null !");
return null;
}
Jedis jedis = null;
try {
jedis = jedisSentinelPool.getResource();
return jedis.rpop(key);
} catch (Exception e) {
log.error("Redis rpop ERROR!", e);
} finally {
if(jedis!=null)
jedis.close();
}
return null;
}
public String lock(String lockName, long acquireTimeout, long lockTimeout) {
if (jedisSentinelPool==null) {
log.warn("jedisSentinelPool is null !");
return null;
}
if (lockName==null) {
log.warn("Key is null !");
return null;
}
Jedis jedis = null;
try {
jedis = jedisSentinelPool.getResource();
String identifier = UUID.randomUUID().toString();
String lockKey = "lock:" + lockName;
int lockExpire = (int)(lockTimeout / 1000);
long end = System.currentTimeMillis() + acquireTimeout;
while (System.currentTimeMillis() < end) {
if (jedis.setnx(lockKey, identifier) == 1){
jedis.expire(lockKey, lockExpire);
return identifier;
}
if (jedis.ttl(lockKey) == -1) {
jedis.expire(lockKey, lockExpire);
}
try {
Thread.sleep(1);
}catch(InterruptedException ie){
Thread.currentThread().interrupt();
}
}
// null indicates that the lock was not acquired
return null;
} catch (Exception e) {
log.error("Redis lock ERROR!", e);
} finally {
if(jedis!=null) {
jedis.close();
}
}
return null;
}
public boolean unlock(final String lockName,final String identifier) {
if (jedisSentinelPool==null) {
String msg = "jedisSentinelPool is null !";
log.error(msg);
return false;
}
if (lockName==null) {
String msg = "Key is null !";
log.warn(msg);
return false;
}
Jedis jedis = null;
try {
jedis = jedisSentinelPool.getResource();
String lockKey = "lock:" + lockName;
while (true){
jedis.watch(lockKey);
if (identifier.equals(jedis.get(lockKey))){
Transaction trans = jedis.multi();
trans.del(lockKey);
List<Object> results = trans.exec();
if (results == null){
continue;
}
return true;
}
jedis.unwatch();
break;
}
return false;
} catch (Exception e) {
String msg = "Redis unlock ERROR!";
log.error(msg, e);
} finally {
if(jedis!=null) {
jedis.close();
}
}
return false;
}
public String lockWithLua(String lockName, long acquireTimeout, long lockTimeout) {
if (jedisSentinelPool==null) {
log.warn("jedisSentinelPool is null !");
return null;
}
if (lockName==null) {
log.warn("Key is null !");
return null;
}
Jedis jedis = null;
try {
jedis = jedisSentinelPool.getResource();
String identifier = UUID.randomUUID().toString();
String lockKey = "lock:" + lockName;
int lockExpire = (int)(lockTimeout / 1000);
long end = System.currentTimeMillis() + acquireTimeout;
while (System.currentTimeMillis() < end) {
String script = "if redis.call('exists', KEYS[1]) == 0 then return redis.call('setex', KEYS[1], unpack(ARGV)) end";
Object result = jedis.eval(script, 1, lockKey, String.valueOf(lockExpire),identifier);
if(LOCK_SUCCESS.equals(result)){
return identifier;
}
try {
Thread.sleep(1);
}catch(InterruptedException ie){
Thread.currentThread().interrupt();
}
}
// null indicates that the lock was not acquired
return null;
} catch (Exception e) {
log.error("Redis lock ERROR!", e);
} finally {
if(jedis!=null) {
jedis.close();
}
}
return null;
}
public boolean unlockWithLua(final String lockName,final String identifier) {
if (jedisSentinelPool==null) {
String msg = "jedisSentinelPool is null !";
log.error(msg);
return false;
}
if (lockName==null) {
String msg = "Key is null !";
log.warn(msg);
return false;
}
Jedis jedis = null;
try {
jedis = jedisSentinelPool.getResource();
String lockKey = "lock:" + lockName;
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
Object result = jedis.eval(script, 1,lockKey, identifier);
if (RELEASE_SUCCESS.equals(result)) {
return true;
}
return false;
} catch (Exception e) {
String msg = "Redis unlock ERROR!";
log.error(msg, e);
} finally {
if(jedis!=null) {
jedis.close();
}
}
return false;
}
/**
* 增加redis缓存,作为锁定对象
* @param lockTarget 锁定目标对象
* @param expire 过期时间/锁定时长,单位/秒
* @return
*/
public boolean tryLock(String lockTarget, int expire) {
if (lockTarget==null) {
log.warn("Key is null !");
return false;
}
Jedis jedis = null;
try {
jedis = jedisSentinelPool.getResource();
String script = "if redis.call('exists', KEYS[1]) == 0 then return redis.call('setex', KEYS[1], unpack(ARGV)) end";
Object result = jedis.eval(script, 1, lockTarget, String.valueOf(expire), lockTarget);
if(LOCK_SUCCESS.equals(result)){
return true;
}
} catch (Exception e) {
log.error("Redis lock ERROR!", e);
} finally {
if(jedis!=null) {
jedis.close();
}
}
return false;
}
/**
* 删除redis缓存
* 解锁目标对象
* @param lockTarget 待解锁目标对象
* @return
*/
public boolean tryUnlock(String lockTarget) {
if (lockTarget==null) {
log.warn("Key is null !");
return false;
}
Jedis jedis = null;
try {
jedis = jedisSentinelPool.getResource();
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
Object result = jedis.eval(script, 1, lockTarget, lockTarget);
if (RELEASE_SUCCESS.equals(result)) {
return true;
}
return false;
} catch (Exception e) {
String msg = "Redis unlock ERROR!";
log.error(msg, e);
} finally {
if(jedis!=null) {
jedis.close();
}
}
return false;
}
//获取Jedis
public Jedis getJedisConnection(){
if (jedisSentinelPool==null) {
log.warn("jedisSentinelPool is null !");
return null;
}
Jedis jedis = jedisSentinelPool.getResource();
return jedis;
}
}
RedisUtil.java
package tf56.payOnlineService.util.redis;
public class RedisUtil extends MyCacheCloudRedisFactory {
private static RedisUtil redisUtil = null;
static {
try {
redisUtil = new RedisUtil();
} catch (Exception e) {
log.error("Init common redis client ERROR !", e);
}
}
/**
* 默认构造函数,会自动从默认配置文件 ["config/CacheCloud.properties"] 读取必要参数
*/
private RedisUtil() throws Exception {
}
public static RedisUtil getInstance() {
return redisUtil;
}
}
使用示例
可根据实际业务场景自定义返回,或者跑异常....
if (!RedisUtil.getInstance().tryLock(lock, 5)) { // expire
return ResultUtils.failed("当前订单列表含有处理中,请等待处理结果或者5秒后重试");
}
来源:CSDN
作者:li_tiantian
链接:https://blog.csdn.net/li_tiantian/article/details/103602437