package com.hujiang.juice.common.utils.cache;
import com.hujiang.juice.common.error.CommonStatusCode;
import com.hujiang.juice.common.exception.CacheException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import redis.clients.jedis.*;
import redis.clients.jedis.exceptions.JedisConnectionException;
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;
/**
* Created by zhouxiang on 2016/8/1.
*/
@Slf4j
public class RedisUtil {
private JedisPool pool = null;
public Jedis getResource() {
return pool.getResource();
}
/**
* <p>传入ip和端口号构建redis 连接池</p>
* @param ip ip
* @param prot 端口
*/
public RedisUtil(String ip, int prot) {
if (pool == null) {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(500);
config.setMaxIdle(5);
config.setMaxWaitMillis(3000);
config.setTestOnBorrow(true);
pool = new JedisPool(config, ip, prot, 5000);
}
}
/**
* <p>传入ip和端口号构建redis 连接池</p>
* @param ip ip
* @param prot 端口
*/
public RedisUtil(String ip, int prot, String password) {
if (pool == null) {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(500);
config.setMaxIdle(5);
config.setMaxWaitMillis(3000);
config.setTestOnBorrow(true);
if(StringUtils.isNotBlank(password))
pool = new JedisPool(config, ip, prot, 5000, password);
else
pool = new JedisPool(config, ip, prot, 5000);
}
}
/**
* <p>通过配置对象 ip 端口 构建连接池</p>
* @param config 配置对象
* @param ip ip
* @param prot 端口
*/
public RedisUtil(JedisPoolConfig config , String ip, int prot){
if (pool == null) {
pool = new JedisPool(config,ip,prot,5000);
}
}
/**
* <p>通过配置对象 ip 端口 超时时间 构建连接池</p>
* @param config 配置对象
* @param ip ip
* @param prot 端口
* @param timeout 超时时间
*/
public RedisUtil(JedisPoolConfig config , String ip, int prot , int timeout){
if (pool == null) {
pool = new JedisPool(config,ip,prot,timeout);
}
}
/**
* <p>通过连接池对象 构建一个连接池</p>
* @param pool 连接池对象
*/
public RedisUtil(JedisPool pool){
if (this.pool == null) {
this.pool = pool;
}
}
/**
* <p>通过key获取储存在redis中的value</p>
* <p>并释放连接</p>
* @param key
* @return 成功返回value 失败返回null
*/
public String get(String key){
Jedis jedis = null;
try{
jedis = pool.getResource();
if(jedis == null) {
throw new CacheException(CommonStatusCode.REDIS_CONNECTION_RESOURCE_NOT_NULL);
}
return jedis.get(key);
} catch (Exception e) {
log.error("redis set error, key : " + key);
throw throwCacheException(e);
} finally {
returnResource(jedis);
}
}
/**
* <p>向redis存入key和value,并释放连接资源</p>
* <p>如果key已经存在 则覆盖</p>
* @param key
* @param value
* @return 成功 返回OK 失败返回 0
*/
public String set(String key,String value){
Jedis jedis = null;
try {
jedis = pool.getResource();
if(jedis == null) {
throw new CacheException(CommonStatusCode.REDIS_CONNECTION_RESOURCE_NOT_NULL);
}
return jedis.set(key, value);
} catch (Exception e) {
log.error("redis set error, key : " + key + " value : " + value);
throw throwCacheException(e);
} finally {
returnResource(jedis);
}
}
/**
* <p>删除指定的key,也可以传入一个包含key的数组</p>
* @param keys 一个key 也可以使 string 数组
* @return 返回删除成功的个数
*/
public Long del(String...keys){
Jedis jedis = null;
try {
jedis = pool.getResource();
if(jedis == null) {
throw new CacheException(CommonStatusCode.REDIS_CONNECTION_RESOURCE_NOT_NULL);
}
return jedis.del(keys);
} catch (Exception e) {
log.error("redis set error, keys : " + Arrays.stream(keys).collect(Collectors.joining(",")));
throw throwCacheException(e);
} finally {
returnResource(jedis);
}
}
/**
* <p>通过key向指定的value值追加值</p>
* @param key
* @param str
* @return 成功返回 添加后value的长度 失败 返回 添加的 value 的长度 异常返回0L
*/
public Long append(String key ,String str){
Jedis jedis = null;
try {
jedis = pool.getResource();
if(jedis == null) {
throw new CacheException(CommonStatusCode.REDIS_CONNECTION_RESOURCE_NOT_NULL);
}
return jedis.append(key, str);
} catch (Exception e) {
log.error("redis set error, key : " + key + " value : " + str);
throw throwCacheException(e);
} finally {
returnResource(jedis);
}
}
/**
* <p>判断key是否存在</p>
* @param key
* @return true OR false
*/
public Boolean exists(String key){
Jedis jedis = null;
try {
jedis = pool.getResource();
if(jedis == null) {
throw new CacheException(CommonStatusCode.REDIS_CONNECTION_RESOURCE_NOT_NULL);
}
return jedis.exists(key);
} catch (Exception e) {
log.error("redis set error, key : " + key);
throw throwCacheException(e);
} finally {
returnResource(jedis);
}
}
public Boolean setex(String key, String value, int expireTime) {
Jedis jedis = null;
try {
jedis = pool.getResource();
if(jedis == null) {
throw new CacheException(CommonStatusCode.REDIS_CONNECTION_RESOURCE_NOT_NULL);
}
return null != jedis.setex(key, expireTime, value);
} catch (Exception e) {
log.error("redis set error, key : " + key + " value : " + value + " expireTime : " + expireTime);
throw throwCacheException(e);
} finally {
returnResource(jedis);
}
}
/**
* <p>队列左插入一个value</p>
* @param listName 队列名
* value 元素值
* @return 插入后队列的元素个数
*/
public Long lPush(String listName, String value) {
Jedis jedis = null;
try {
jedis = pool.getResource();
if(jedis == null) {
throw new CacheException(CommonStatusCode.REDIS_CONNECTION_RESOURCE_NOT_NULL);
}
return jedis.lpush(listName, value);
} catch (Exception e) {
log.error("redis lPush error, ListName : " + listName + " value : " + value);
throw throwCacheException(e);
} finally {
returnResource(jedis);
}
}
/**
* <p>队列右弹出一个元素</p>
* @param listName 队列名
*
* @return 元素值
*/
public String rPop(String listName) {
Jedis jedis = null;
try {
jedis = pool.getResource();
if(jedis == null) {
throw new CacheException(CommonStatusCode.REDIS_CONNECTION_RESOURCE_NOT_NULL);
}
return jedis.rpop(listName);
} catch (Exception e) {
log.error("redis rPop error, ListName : " + listName);
throw throwCacheException(e);
} finally {
returnResource(jedis);
}
}
/**
* <p>队列元素个数</p>
* @param listName 队列名
*
* @return 元素个数
*/
public Long llen(String listName) {
Jedis jedis = null;
try {
jedis = pool.getResource();
if(jedis == null) {
throw new CacheException(CommonStatusCode.REDIS_CONNECTION_RESOURCE_NOT_NULL);
}
return jedis.llen(listName);
} catch (Exception e) {
log.error("redis llen error, ListName : " + listName);
throw throwCacheException(e);
} finally {
returnResource(jedis);
}
}
/**
* <p>在指定的Set中插入一个元素</p>
* @param setName set名
* value
* @return Set中的元素个数
*/
public Long sadd(String setName, String value) {
Jedis jedis = null;
try {
jedis = pool.getResource();
if(jedis == null) {
throw new CacheException(CommonStatusCode.REDIS_CONNECTION_RESOURCE_NOT_NULL);
}
return jedis.sadd(setName, value);
} catch (Exception e) {
log.error("redis sadd error, setName : " + setName + " value : " + value);
throw throwCacheException(e);
} finally {
returnResource(jedis);
}
}
/**
* <p>在指定的Set中删除一个元素</p>
* @param setName set名
* value
* @return Set中的元素个数
*/
public Long srem(String setName, String value) {
Jedis jedis = null;
try {
jedis = pool.getResource();
if(jedis == null) {
throw new CacheException(CommonStatusCode.REDIS_CONNECTION_RESOURCE_NOT_NULL);
}
return jedis.srem(setName, value);
} catch (Exception e) {
log.error("redis srem error, setName : " + setName + " value : " + value);
throw throwCacheException(e);
} finally {
returnResource(jedis);
}
}
/**
* <p>返回Set中的所有元素</p>
* @param setName set名
* value
* @return 元素值
*/
public Set<String> smembers(String setName) {
Jedis jedis = null;
try {
jedis = pool.getResource();
if(jedis == null) {
throw new CacheException(CommonStatusCode.REDIS_CONNECTION_RESOURCE_NOT_NULL);
}
return jedis.smembers(setName);
} catch (Exception e) {
log.error("redis smembers error, setName : " + setName);
throw throwCacheException(e);
} finally {
returnResource(jedis);
}
}
public void subscribe(JedisPubSub subscriber, String channel) {
Jedis jedis = null;
try {
jedis = pool.getResource();
if(jedis == null) {
throw new CacheException(CommonStatusCode.REDIS_CONNECTION_RESOURCE_NOT_NULL);
}
jedis.subscribe(subscriber, channel);
} catch (Exception e) {
log.error("redis subscribe error, channel : " + channel);
throw throwCacheException(e);
} finally {
returnResource(jedis);
}
}
public Long publish(String channel, String message) {
Jedis jedis = null;
try {
jedis = pool.getResource();
if(jedis == null) {
throw new CacheException(CommonStatusCode.REDIS_CONNECTION_RESOURCE_NOT_NULL);
}
return jedis.publish(channel, message);
} catch (Exception e) {
log.error("redis publish error, channel : " + channel + ", message : " + message);
throw throwCacheException(e);
} finally {
returnResource(jedis);
}
}
public boolean unLock(String key) {
Jedis jedis = null;
try {
jedis = pool.getResource();
if(jedis == null) {
throw new CacheException(CommonStatusCode.REDIS_CONNECTION_RESOURCE_NOT_NULL);
}
return jedis.del(key) > 0;
} catch (Exception e) {
log.error("set redis unlock error!");
throw throwCacheException(e);
} finally {
returnResource(jedis);
}
}
public boolean lock(String key, int seconds, String value) {
Jedis jedis = null;
Transaction tx;
try {
jedis = pool.getResource();
if(jedis == null) {
throw new CacheException(CommonStatusCode.REDIS_CONNECTION_RESOURCE_NOT_NULL);
}
jedis.watch(key);
if (!jedis.exists(key)) {
tx = jedis.multi();
tx.setex(key, seconds, value);
if (null != tx.exec()) {
return true;
}
}
return false;
} catch (Exception e) {
log.error("set redis lock key error!");
throw throwCacheException(e);
} finally {
if (null != jedis) {
jedis.unwatch();
}
returnResource(jedis);
}
}
private CacheException throwCacheException(Exception e) {
log.error("error due to : " + e.getMessage());
if(e instanceof JedisConnectionException) {
return new CacheException(CommonStatusCode.REDIS_CONNECTION_ERROR.getStatus(), "jedis connection exception");
} else if(e instanceof CacheException) {
return (CacheException)e;
}
return new CacheException(CommonStatusCode.REDIS_OPERATION_ERROR.getStatus(), e.getMessage());
}
/**
* 返还到连接池
*
* @param jedis
*/
public static void returnResource(Jedis jedis) {
if (jedis != null) {
jedis.close();
}
}
}