summaryrefslogtreecommitdiff
path: root/src/main/java/com/nis/util/JedisClusterUtils.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/nis/util/JedisClusterUtils.java')
-rw-r--r--src/main/java/com/nis/util/JedisClusterUtils.java361
1 files changed, 361 insertions, 0 deletions
diff --git a/src/main/java/com/nis/util/JedisClusterUtils.java b/src/main/java/com/nis/util/JedisClusterUtils.java
new file mode 100644
index 0000000..e5d1044
--- /dev/null
+++ b/src/main/java/com/nis/util/JedisClusterUtils.java
@@ -0,0 +1,361 @@
+package com.nis.util;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Lists;
+import com.nis.restful.RestBusinessCode;
+import com.nis.restful.ServiceRuntimeException;
+import com.nis.web.service.SpringContextHolder;
+
+import redis.clients.jedis.JedisCluster;
+import redis.clients.jedis.exceptions.JedisException;
+
+/**
+ * @ClassName: JedisClusterUtils
+ * @Description: redis-cluster库工具类
+ * @author (rkg)
+ * @date 2018年12月01日 上午10:31:00
+ * @version V1.0
+ */
+public class JedisClusterUtils {
+ private static Logger logger = LoggerFactory.getLogger(JedisClusterUtils.class);
+
+ /**
+ * 获取缓存
+ *
+ * @param key 键
+ * @return 值
+ */
+ public static String get(String key) {
+ String value = null;
+ JedisCluster jedis = null;
+ try {
+ jedis = getResource();
+ if (jedis.exists(key)) {
+ value = jedis.get(key);
+ value = StringUtils.isNotBlank(value) && !"nil".equalsIgnoreCase(value) ? value : null;
+ logger.debug("get {} = {}", key, value);
+ }
+ } catch (Exception e) {
+ throw new ServiceRuntimeException("从redis-cluster中获取" + key + "对应的值失败",
+ RestBusinessCode.KeyNotExistsInRedis.getValue());
+ } finally {
+ returnResource(jedis);
+ }
+ return value;
+ }
+
+ /**
+ * 获取缓存
+ *
+ * @param key 键
+ * @return 值
+ */
+ public static Object getObject(String key) {
+ Object value = null;
+ JedisCluster jedis = null;
+ try {
+ jedis = getResource();
+ if (jedis.exists(getBytesKey(key))) {
+ value = toObject(jedis.get(getBytesKey(key)));
+ logger.debug("getObject {} = {}", key, value);
+ }
+ } catch (Exception e) {
+ throw new ServiceRuntimeException("从redis-cluster中获取" + key + "对应的值失败",
+ RestBusinessCode.KeyNotExistsInRedis.getValue());
+ } finally {
+ returnResource(jedis);
+ }
+ return value;
+ }
+
+ /**
+ * <b>可以作为获取唯一id的方法</b><br/>
+ * 将key对应的value加上指定的值,只有value可以转为数字时该方法才可用
+ *
+ * @param String key
+ * @param long number 要减去的值
+ * @return long 相加后的值
+ */
+ public static long incrBy(String key, long number) {
+ JedisCluster jedis = getResource();
+ long len = jedis.incrBy(key, number);
+ returnResource(jedis);
+ return len;
+ }
+
+ /**
+ * 设置缓存
+ *
+ * @param key 键
+ * @param value 值
+ * @param cacheSeconds 超时时间,0为不超时
+ * @return
+ */
+ public static String set(String key, String value, int cacheSeconds) {
+ String result = null;
+ JedisCluster jedis = null;
+ try {
+ jedis = getResource();
+ result = jedis.set(key, value);
+ if (cacheSeconds != 0) {
+ jedis.expire(key, cacheSeconds);
+ }
+ logger.debug("set {} = {}", key, value);
+ } catch (Exception e) {
+ throw new ServiceRuntimeException("向redis-cluster中设置zset失败,key=" + key + ",value=" + value,
+ RestBusinessCode.ZsetFailed.getValue());
+ } finally {
+ returnResource(jedis);
+ }
+ return result;
+ }
+
+ /**
+ * 获取List缓存
+ *
+ * @param key 键
+ * @return 值
+ */
+ public static List<String> getList(String key) {
+ List<String> value = null;
+ JedisCluster jedis = null;
+ try {
+ jedis = getResource();
+ if (jedis.exists(key)) {
+ value = jedis.lrange(key, 0, -1);
+ logger.debug("getList {} = {}", key, value);
+ }
+ } catch (Exception e) {
+ throw new ServiceRuntimeException("从redis-cluster中获取" + key + "对应的值失败",
+ RestBusinessCode.KeyNotExistsInRedis.getValue());
+ } finally {
+ returnResource(jedis);
+ }
+ return value;
+ }
+
+ /**
+ * 获取List缓存
+ *
+ * @param key 键
+ * @return 值
+ */
+ public static List<Object> getObjectList(String key) {
+ List<Object> value = null;
+ JedisCluster jedis = null;
+ try {
+ jedis = getResource();
+ if (jedis.exists(getBytesKey(key))) {
+ List<byte[]> list = jedis.lrange(getBytesKey(key), 0, -1);
+ value = Lists.newArrayList();
+ for (byte[] bs : list) {
+ value.add(toObject(bs));
+ }
+ logger.debug("getObjectList {} = {}", key, value);
+ }
+ } catch (Exception e) {
+ throw new ServiceRuntimeException("从redis-cluster中获取" + key + "对应的值失败",
+ RestBusinessCode.KeyNotExistsInRedis.getValue());
+ } finally {
+ returnResource(jedis);
+ }
+ return value;
+ }
+
+ /**
+ * 缓存是否存在
+ *
+ * @param key 键
+ * @return
+ */
+ public static boolean exists(String key) {
+ boolean result = false;
+ JedisCluster jedis = null;
+ try {
+ jedis = getResource();
+ result = jedis.exists(key);
+ logger.debug("exists {}", key);
+ } catch (Exception e) {
+ throw new ServiceRuntimeException("从redis-cluster中判断" + key + "是否存在失败",
+ RestBusinessCode.ExistsKeyFailed.getValue());
+ } finally {
+ returnResource(jedis);
+ }
+ return result;
+ }
+
+ /**
+ * 缓存是否存在
+ *
+ * @param key 键
+ * @return
+ */
+ public static boolean existsObject(String key) {
+ boolean result = false;
+ JedisCluster jedis = null;
+ try {
+ jedis = getResource();
+ result = jedis.exists(getBytesKey(key));
+ logger.debug("existsObject {}", key);
+ } catch (Exception e) {
+ throw new ServiceRuntimeException("从redis-cluster中判断" + key + "是否存在失败",
+ RestBusinessCode.ExistsKeyFailed.getValue());
+ } finally {
+ returnResource(jedis);
+ }
+ return result;
+ }
+
+ /**
+ * 获取资源
+ *
+ * @return
+ * @throws JedisException
+ */
+ public static JedisCluster getResource() throws JedisException {
+ JedisCluster jedisCluster = SpringContextHolder.getBean(JedisCluster.class);
+ if (jedisCluster == null) {
+ throw new ServiceRuntimeException("无法获取redis-cluster连接,请联系管理员检查程序",
+ RestBusinessCode.CannotConnectionRedis.getValue());
+ }
+ return jedisCluster;
+
+ }
+
+ /**
+ * 释放资源
+ *
+ * @param jedis
+ * @param isBroken
+ */
+ public static void returnBrokenResource(JedisCluster jedis) {
+ if (jedis != null) {
+ try {
+ jedis.close();
+ } catch (Exception e) {
+ throw new ServiceRuntimeException("释放redis-cluster连接失败", RestBusinessCode.CannotConnectionRedis.getValue());
+ }
+ }
+ }
+
+ /**
+ * 释放资源
+ *
+ * @param jedis
+ * @param isBroken
+ */
+ public static void returnResource(JedisCluster jedis) {
+ if (jedis != null) {
+ try {
+ jedis.close();
+ } catch (Exception e) {
+ throw new ServiceRuntimeException("释放redis-cluster连接失败", RestBusinessCode.CannotConnectionRedis.getValue());
+ }
+ }
+ }
+
+ /**
+ * 获取byte[]类型Key
+ *
+ * @param key
+ * @return
+ */
+ public static byte[] getBytesKey(Object object) {
+ if (object instanceof String) {
+ return StringUtils.getBytes((String) object);
+ } else {
+ return ObjectUtils.serialize(object);
+ }
+ }
+
+ /**
+ * Object转换byte[]类型
+ *
+ * @param key
+ * @return
+ */
+ public static byte[] toBytes(Object object) {
+ return ObjectUtils.serialize(object);
+ }
+
+ /**
+ * byte[]型转换Object
+ *
+ * @param key
+ * @return
+ */
+ public static Object toObject(byte[] bytes) {
+ return ObjectUtils.unserialize(bytes);
+ }
+
+ // 设置成功返回的结果OK
+ private static final String LOCK_SUCCESS = "OK";
+ // NX -- Only set the key if it does not already exist. XX -- Only set the key
+ // if it already exist
+ private static final String SET_IF_NOT_EXIST = "NX";
+ // 失效单位秒(EX)还是毫秒(PX)
+ private static final String SET_WITH_EXPIRE_TIME = "EX";
+ private static final Long UNLOCK_SUCCESS = 1L;
+
+ /**
+ * 尝试获取分布式锁,如果没有key就set,有key就不操作
+ *
+ * @param requestId 请求标识(UUID.randomUUID().toString()),正常情况下是谁加的锁,谁去解锁不能a加的锁,b去解锁
+ * @return 是否获取成功
+ */
+ public static Boolean lock(String requestId) {
+ String key = "uiAndServiceConfigSyncLock";
+ String var1 = getResource().set(key, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME,
+ Constants.REDISLOCKTIME);
+ if (LOCK_SUCCESS.equals(var1)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * 解锁操作
+ *
+ * @param value 客户端标识(requestId)
+ * @return
+ */
+ public static Boolean unLock(String value) {
+ String key = "uiAndServiceConfigSyncLock";
+ // 这个字符串是个lua脚本,代表的意思是如果根据key拿到的value跟传入的value相同就执行del,否则就返回0【保证安全性】
+ String luaScript = "if redis.call(\"get\",KEYS[1]) == ARGV[1] then return redis.call(\"del\",KEYS[1]) else return 0 end";
+ // 这个命令就是去执行lua脚本,KEYS的集合就是第二个参数,ARGV的集合就是第三参数【保证解锁的原子操作】
+ Object var2 = getResource().eval(luaScript, Collections.singletonList(key), Collections.singletonList(value));
+ if (UNLOCK_SUCCESS == var2) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * 重试机制
+ *
+ * @param value 客户端标识
+ * @return
+ */
+ public static Boolean lockRetry(String value) {
+ Boolean flag = false;
+ try {
+ for (int i = 0; i < Constants.REDISRETRYNUM; i++) {
+ flag = lock(value);
+ if (flag) {
+ break;
+ }
+ Thread.sleep(1000);
+ }
+ } catch (Exception e) {
+ logger.error("尝试获取redis分布式锁失败,失败原因:{}", ExceptionUtil.getExceptionMsg(e));
+ }
+ return flag;
+ }
+
+}