ソースを参照

增加apm-redis包,来兼容集成框架redis包

lixing 2 年 前
コミット
cbea2c5c78
37 ファイル変更3892 行追加0 行削除
  1. 20 0
      apm-common/src/main/java/com/persagy/common/annotation/IdGeneratorPrefix.java
  2. 43 0
      apm-common/src/main/java/com/persagy/common/config/DefaultIdentifierGenerator.java
  3. 38 0
      apm-common/src/main/java/com/persagy/common/utils/IdGenerator.java
  4. 205 0
      apm-common/src/main/java/com/persagy/common/utils/Sequence.java
  5. 37 0
      apm-common/src/main/java/com/persagy/common/utils/StringUtil.java
  6. 5 0
      apm-parent/pom.xml
  7. 43 0
      apm-redis/pom.xml
  8. 114 0
      apm-redis/src/main/java/com/persagy/common/RedisAutoConfigure.java
  9. 86 0
      apm-redis/src/main/java/com/persagy/common/constant/CommonConstant.java
  10. 16 0
      apm-redis/src/main/java/com/persagy/common/exception/LockException.java
  11. 46 0
      apm-redis/src/main/java/com/persagy/common/lock/DistributedLock.java
  12. 74 0
      apm-redis/src/main/java/com/persagy/common/lock/Lock.java
  13. 21 0
      apm-redis/src/main/java/com/persagy/common/model/LockModel.java
  14. 234 0
      apm-redis/src/main/java/com/persagy/common/redis/aop/LockAop.java
  15. 173 0
      apm-redis/src/main/java/com/persagy/common/redis/base/HashOperations.java
  16. 138 0
      apm-redis/src/main/java/com/persagy/common/redis/base/KeyOperations.java
  17. 191 0
      apm-redis/src/main/java/com/persagy/common/redis/base/ListOperations.java
  18. 78 0
      apm-redis/src/main/java/com/persagy/common/redis/base/RedissonTemplate.java
  19. 207 0
      apm-redis/src/main/java/com/persagy/common/redis/base/StringOperations.java
  20. 239 0
      apm-redis/src/main/java/com/persagy/common/redis/boot/RedisBeanContext.java
  21. 27 0
      apm-redis/src/main/java/com/persagy/common/redis/constant/RedisToolsConstant.java
  22. 106 0
      apm-redis/src/main/java/com/persagy/common/redis/factory/ClusterRedissionConfig.java
  23. 110 0
      apm-redis/src/main/java/com/persagy/common/redis/factory/MasterSlaveRedissionConfig.java
  24. 41 0
      apm-redis/src/main/java/com/persagy/common/redis/factory/RedissonClientFactory.java
  25. 106 0
      apm-redis/src/main/java/com/persagy/common/redis/factory/ReplicatedRedissionConfig.java
  26. 108 0
      apm-redis/src/main/java/com/persagy/common/redis/factory/SentinelRedissionConfig.java
  27. 88 0
      apm-redis/src/main/java/com/persagy/common/redis/factory/SingleRedissionConfig.java
  28. 43 0
      apm-redis/src/main/java/com/persagy/common/redis/model/CodecModel.java
  29. 14 0
      apm-redis/src/main/java/com/persagy/common/redis/model/Model.java
  30. 40 0
      apm-redis/src/main/java/com/persagy/common/redis/model/SerializerModel.java
  31. 31 0
      apm-redis/src/main/java/com/persagy/common/redis/properties/CacheManagerProperties.java
  32. 155 0
      apm-redis/src/main/java/com/persagy/common/redis/properties/MultipleServerConfig.java
  33. 419 0
      apm-redis/src/main/java/com/persagy/common/redis/properties/RedissonProperties.java
  34. 65 0
      apm-redis/src/main/java/com/persagy/common/redis/properties/SingleServerConfig.java
  35. 493 0
      apm-redis/src/main/java/com/persagy/common/redis/template/RedissonTemplateImpl.java
  36. 37 0
      apm-redis/src/main/java/com/persagy/common/utils/StringUtil.java
  37. 1 0
      pom.xml

+ 20 - 0
apm-common/src/main/java/com/persagy/common/annotation/IdGeneratorPrefix.java

@@ -0,0 +1,20 @@
+package com.persagy.common.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * @version 
+ * @description ID自动生成前缀 {@link}
+ * @company persagy
+ * @author zhangqiankun
+ * @since 2020年9月29日:	下午12:10:37
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+@Inherited
+@Documented
+public @interface IdGeneratorPrefix {
+	
+	String value();
+	
+}

+ 43 - 0
apm-common/src/main/java/com/persagy/common/config/DefaultIdentifierGenerator.java

@@ -0,0 +1,43 @@
+package com.persagy.common.config;
+
+import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
+import com.persagy.common.annotation.IdGeneratorPrefix;
+import com.persagy.common.utils.IdGenerator;
+import com.persagy.common.utils.StringUtil;
+
+/**
+ * @version 
+ * @description 若需要自定义ID生成规则,请重写对应方法
+ * @company persagy
+ * @author zhangqiankun
+ * @since 2020年9月29日:	上午11:50:05
+ */
+public class DefaultIdentifierGenerator implements IdentifierGenerator {
+
+	@Override
+	public Long nextId(Object entity) {
+		return assignLongId();
+	}
+	
+	@Override
+	public String nextUUID(Object entity) {
+		IdGeneratorPrefix prefix = entity.getClass().getAnnotation(IdGeneratorPrefix.class);
+		if (prefix == null || StringUtil.isBlank(prefix.value())) {
+			return assignStringId();
+		}
+        return assignStringId(prefix.value());
+    }
+	
+	public Long assignLongId() {
+		return IdGenerator.getSnowId();
+	}
+	
+	public String assignStringId() {
+		return IdGenerator.getSnowIdStr();
+	}
+
+	public String assignStringId(String prefix) {
+		return IdGenerator.getSnowIdStr(prefix);
+	}
+
+}

+ 38 - 0
apm-common/src/main/java/com/persagy/common/utils/IdGenerator.java

@@ -0,0 +1,38 @@
+package com.persagy.common.utils;
+
+import cn.hutool.core.util.IdUtil;
+
+/**
+ * 高效分布式ID生成算法(sequence),基于Snowflake算法优化实现64位自增ID算法。
+ * 其中解决时间回拨问题的优化方案如下:
+ * 1. 如果发现当前时间少于上次生成id的时间(时间回拨),着计算回拨的时间差
+ * 2. 如果时间差(offset)小于等于5ms,着等待 offset * 2 的时间再生成
+ * 3. 如果offset大于5,则直接抛出异常
+ *
+ * @description 
+ * @author persagy
+ * @since 2020年11月4日:	下午8:09:02
+ */
+public class IdGenerator {
+    private static Sequence WORKER = new Sequence();
+
+    public static long getSnowId() {
+        return WORKER.nextId();
+    }
+
+    public static String getSnowIdStr() {
+        return String.valueOf(WORKER.nextId());
+    }
+    
+    public static String getSnowIdStr(String prefix) {
+        return prefix + WORKER.nextId();
+    }
+    
+    public static String getUUID() {
+    	return IdUtil.fastSimpleUUID();
+    }
+    
+    public static String getUUID(String prefix) {
+    	return prefix + IdUtil.fastSimpleUUID();
+    }
+}

+ 205 - 0
apm-common/src/main/java/com/persagy/common/utils/Sequence.java

@@ -0,0 +1,205 @@
+package com.persagy.common.utils;
+
+import cn.hutool.core.date.SystemClock;
+import cn.hutool.core.lang.Assert;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
+import lombok.extern.slf4j.Slf4j;
+
+import java.lang.management.ManagementFactory;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.util.concurrent.ThreadLocalRandom;
+
+/**
+ * 分布式高效有序ID生成器
+ * 优化开源项目:http://git.oschina.net/yu120/sequence
+ *
+ * Twitter_Snowflake<br>
+ * SnowFlake的结构如下(每部分用-分开):<br>
+ * 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 -
+ * 000000000000 <br>
+ * 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0<br>
+ * 41位时间截(毫秒级),注意,41位时间截不是存储当前时间的时间截,而是存储时间截的差值(当前时间截 - 开始时间截)
+ * 得到的值),这里的的开始时间截,一般是我们的id生成器开始使用的时间,由我们程序来指定的(如下下面程序IdWorker类的startTime属性)。41位的时间截,可以使用69年,年T
+ * = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69<br>
+ * 10位的数据机器位,可以部署在1024个节点,包括5位datacenterId和5位workerId<br>
+ * 12位序列,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间截)产生4096个ID序号<br>
+ * 加起来刚好64位,为一个Long型。<br>
+ * SnowFlake的优点是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分),并且效率较高,经测试,SnowFlake每秒能够产生26万ID左右。
+ *
+ * @description 
+ * @author persagy
+ * @since 2020年11月4日:	下午8:09:02
+ */
+@Slf4j
+public class Sequence {
+    /**
+     * 时间起始标记点,作为基准,一般取系统的最近时间(一旦确定不能变动)
+     */
+    private final long twepoch = 1288834974657L;
+    /**
+     * 机器标识位数
+     */
+    private final long workerIdBits = 5L;
+    private final long datacenterIdBits = 5L;
+    private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
+    private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
+    /**
+     * 毫秒内自增位
+     */
+    private final long sequenceBits = 12L;
+    private final long workerIdShift = sequenceBits;
+    private final long datacenterIdShift = sequenceBits + workerIdBits;
+    /**
+     * 时间戳左移动位
+     */
+    private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
+    private final long sequenceMask = -1L ^ (-1L << sequenceBits);
+
+    private final long workerId;
+
+    /**
+     * 数据标识 ID 部分
+     */
+    private final long datacenterId;
+    /**
+     * 并发控制
+     */
+    private long sequence = 0L;
+    /**
+     * 上次生产 ID 时间戳
+     */
+    private long lastTimestamp = -1L;
+
+    /**
+     * 时间回拨最长时间(ms),超过这个时间就抛出异常
+     */
+    private long timestampOffset = 5L;
+
+    public Sequence() {
+        this.datacenterId = getDatacenterId(maxDatacenterId);
+        this.workerId = getMaxWorkerId(datacenterId, maxWorkerId);
+    }
+
+    /**
+     * <p>
+     * 有参构造器
+     * </p>
+     *
+     * @param workerId     工作机器 ID
+     * @param datacenterId 序列号
+     */
+    public Sequence(long workerId, long datacenterId) {
+        Assert.isFalse(workerId > maxWorkerId || workerId < 0,
+                String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
+        Assert.isFalse(datacenterId > maxDatacenterId || datacenterId < 0,
+                String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
+        this.workerId = workerId;
+        this.datacenterId = datacenterId;
+    }
+
+    /**
+     * <p>
+     * 获取 maxWorkerId
+     * </p>
+     */
+    protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) {
+        StringBuilder mpid = new StringBuilder();
+        mpid.append(datacenterId);
+        String name = ManagementFactory.getRuntimeMXBean().getName();
+        if (StrUtil.isNotEmpty(name)) {
+            /*
+             * GET jvmPid
+             */
+            mpid.append(name.split(StringPool.AT)[0]);
+        }
+        /*
+         * MAC + PID 的 hashcode 获取16个低位
+         */
+        return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1);
+    }
+
+    /**
+     * <p>
+     * 数据标识id部分
+     * </p>
+     */
+    protected static long getDatacenterId(long maxDatacenterId) {
+        long id = 0L;
+        try {
+            InetAddress ip = InetAddress.getLocalHost();
+            NetworkInterface network = NetworkInterface.getByInetAddress(ip);
+            if (network == null) {
+                id = 1L;
+            } else {
+                byte[] mac = network.getHardwareAddress();
+                if (null != mac) {
+                    id = ((0x000000FF & (long) mac[mac.length - 1]) | (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6;
+                    id = id % (maxDatacenterId + 1);
+                }
+            }
+        } catch (Exception e) {
+            log.warn(" getDatacenterId: " + e.getMessage());
+        }
+        return id;
+    }
+
+    /**
+     * 获取下一个ID
+     *
+     * @return
+     */
+    public synchronized long nextId() {
+        long timestamp = timeGen();
+        //闰秒
+        if (timestamp < lastTimestamp) {
+            long offset = lastTimestamp - timestamp;
+            if (offset <= timestampOffset) {
+                try {
+                    wait(offset << 1);
+                    timestamp = timeGen();
+                    if (timestamp < lastTimestamp) {
+                        throw new RuntimeException(String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", offset));
+                    }
+                } catch (Exception e) {
+                    throw new RuntimeException(e);
+                }
+            } else {
+                throw new RuntimeException(String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", offset));
+            }
+        }
+
+        if (lastTimestamp == timestamp) {
+            // 相同毫秒内,序列号自增
+            sequence = (sequence + 1) & sequenceMask;
+            if (sequence == 0) {
+                // 同一毫秒的序列数已经达到最大
+                timestamp = tilNextMillis(lastTimestamp);
+            }
+        } else {
+            // 不同毫秒内,序列号置为 1 - 3 随机数
+            sequence = ThreadLocalRandom.current().nextLong(1, 3);
+        }
+
+        lastTimestamp = timestamp;
+
+        // 时间戳部分 | 数据中心部分 | 机器标识部分 | 序列号部分
+        return ((timestamp - twepoch) << timestampLeftShift)
+                | (datacenterId << datacenterIdShift)
+                | (workerId << workerIdShift)
+                | sequence;
+    }
+
+    protected long tilNextMillis(long lastTimestamp) {
+        long timestamp = timeGen();
+        while (timestamp <= lastTimestamp) {
+            timestamp = timeGen();
+        }
+        return timestamp;
+    }
+
+    protected long timeGen() {
+        return SystemClock.now();
+    }
+}

+ 37 - 0
apm-common/src/main/java/com/persagy/common/utils/StringUtil.java

@@ -0,0 +1,37 @@
+package com.persagy.common.utils;
+
+import cn.hutool.core.util.StrUtil;
+
+/**
+ * @version 
+ * @description 
+ * @company persagy
+ * @author zhangqiankun
+ * @since 2020年8月26日:	下午5:22:35
+ */
+public class StringUtil extends StrUtil {
+	
+	/**
+	 * 判断两个字符串是否都为空,或都不为空
+	 * @return true-全空、全不为空;否则-false
+	 */
+	public static boolean concurIsNullOrExists(String param1, String param2) {
+		if (isBlank(param1) && isBlank(param2)) {
+			return true;
+		} 
+		if (isNotBlank(param1) && isNotBlank(param2)) {
+			return true;
+		}
+		return false;
+	}
+	
+	
+	/**
+	 * 移除字符串中指定的前缀和后缀
+	 */
+	public static String removePreAndSuffix(String param, String prefix, String suffix) {
+		param = StringUtil.removePrefix(param, prefix);
+		return StringUtil.removeSuffix(param, suffix);
+	}
+	
+}

+ 5 - 0
apm-parent/pom.xml

@@ -77,6 +77,11 @@
 			</dependency>
 			<dependency>
 				<groupId>com.persagy</groupId>
+				<artifactId>starter-log</artifactId>
+				<version>${passcloud.version}</version>
+			</dependency>
+			<dependency>
+				<groupId>com.persagy</groupId>
 				<artifactId>starter-databases</artifactId>
 				<version>${passcloud.version}</version>
 			</dependency>

+ 43 - 0
apm-redis/pom.xml

@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>apm-basics</artifactId>
+        <groupId>com.persagy</groupId>
+        <version>v1.3.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>apm-redis</artifactId>
+
+    <repositories>
+        <repository>
+            <id>persagy</id>
+            <name>releases Repository</name>
+            <url>http://47.93.132.139:8081/nexus/content/repositories/persagy/</url>
+        </repository>
+        <repository>
+            <id>integrated</id>
+            <name>releases Repository</name>
+            <url>http://47.93.132.139:8081/nexus/content/repositories/integrated/</url>
+        </repository>
+    </repositories>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.persagy</groupId>
+            <artifactId>starter-redis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.persagy</groupId>
+            <artifactId>starter-log</artifactId>
+        </dependency>
+    </dependencies>
+
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+    </properties>
+
+</project>

+ 114 - 0
apm-redis/src/main/java/com/persagy/common/RedisAutoConfigure.java

@@ -0,0 +1,114 @@
+package com.persagy.common;
+
+import com.persagy.common.redis.aop.LockAop;
+import com.persagy.common.redis.base.RedissonTemplate;
+import com.persagy.common.redis.boot.RedisBeanContext;
+import com.persagy.common.redis.factory.RedissonClientFactory;
+import com.persagy.common.redis.properties.CacheManagerProperties;
+import com.persagy.common.redis.properties.RedissonProperties;
+import com.persagy.common.redis.template.RedissonTemplateImpl;
+import org.redisson.api.RedissonClient;
+import org.redisson.spring.data.connection.RedissonConnectionFactory;
+import org.redisson.spring.starter.RedissonAutoConfiguration;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.AutoConfigureBefore;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.data.redis.serializer.RedisSerializer;
+
+/***
+ * @Description: redisson的配置类
+ * @author: lijie
+ * @Date:2020/9/29 9:41
+ * Update By lijie 2020/9/29 9:41
+ */
+@Configuration
+@EnableConfigurationProperties({RedissonProperties.class, CacheManagerProperties.class})
+@ConditionalOnClass({RedissonProperties.class})
+@EnableCaching
+@AutoConfigureBefore({RedissonAutoConfiguration.class})
+public class RedisAutoConfigure {
+	
+
+    @Autowired
+    private RedissonProperties redissonProperties;
+
+    @Bean
+    public RedisSerializer<String> redisKeySerializer() {
+        return RedisSerializer.string();
+    }
+
+    @Bean
+    public RedisSerializer<Object> redisValueSerializer() {
+        return redissonProperties.getSerializerModel().getSerializerType();
+    }
+    
+    @Bean(name = "redisValueJavaSerializer")
+    public RedisSerializer<Object> redisValueJavaSerializer() {
+        return RedisSerializer.java();
+    }
+
+
+    @Bean
+    @ConditionalOnMissingBean(LockAop.class)
+    public LockAop lockAop() {
+        return new LockAop();
+    }
+
+    @Bean
+    @ConditionalOnMissingBean(RedissonTemplate.class)
+    public RedissonTemplate redissonTemplate() {
+        return new RedissonTemplateImpl(redissonProperties.getDatabase());
+    }
+
+    @Bean
+    public RedisBeanContext redisBeanContext(ApplicationContext applicationContext) {
+        return new RedisBeanContext();
+    }
+
+	@Bean(name = "redisTemplate")
+    @ConditionalOnMissingBean(name = "redisTemplate")
+    public RedisTemplate<String, Object> redisTemplate(RedissonConnectionFactory redissonConnectionFactory,
+    		RedisSerializer<String> redisKeySerializer, RedisSerializer<Object> redisValueSerializer) {
+        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
+        template.setConnectionFactory(redissonConnectionFactory);
+        
+        // 设置value的序列化规则和 key的序列化规则
+        template.setKeySerializer(redisKeySerializer);
+        template.setValueSerializer(redisValueSerializer);
+        template.setHashKeySerializer(redisKeySerializer);
+        template.setHashValueSerializer(redisValueSerializer);
+        
+        template.afterPropertiesSet();
+        return template;
+    }
+
+    @Bean(name = "stringRedisTemplate")
+    @ConditionalOnMissingBean(name = {"stringRedisTemplate"})
+    public StringRedisTemplate stringRedisTemplate(RedissonConnectionFactory redissonConnectionFactory) {
+        StringRedisTemplate template = new StringRedisTemplate();
+        template.setConnectionFactory(redissonConnectionFactory);
+        return template;
+    }
+    
+    @Bean
+    @ConditionalOnMissingBean(RedisConnectionFactory.class)
+    public RedissonConnectionFactory redissonConnectionFactory(RedissonClient redissonClient) {
+        return new RedissonConnectionFactory(redissonClient);
+    }
+    
+    @Bean(destroyMethod = "shutdown")
+    @ConditionalOnMissingBean(RedissonClient.class)
+    public RedissonClient redissonClient() {
+    	return RedissonClientFactory.redissonClient(redissonProperties);
+    }
+    
+}

+ 86 - 0
apm-redis/src/main/java/com/persagy/common/constant/CommonConstant.java

@@ -0,0 +1,86 @@
+package com.persagy.common.constant;
+
+/**
+ * 全局公共常量
+ *
+ * @description 
+ * @author persagy
+ * @since 2020年11月4日:	下午8:09:02
+ */
+public interface CommonConstant {
+	
+    /**项目版本号(banner使用)*/
+    String PROJECT_VERSION = "3.7";
+
+    /**token请求头名称*/
+    String TOKEN_HEADER = "Authorization";
+
+    /**The access token issued by the authorization server. This value is REQUIRED.*/
+    String ACCESS_TOKEN = "access_token";
+
+    String BEARER_TYPE = "Bearer";
+
+    /**标签 header key*/
+    String HEADER_LABEL = "x-label";
+
+    /**标签 header 分隔符*/
+    String HEADER_LABEL_SPLIT = ",";
+
+    /**标签或 名称*/
+    String LABEL_OR = "labelOr";
+
+    /**标签且 名称*/
+    String LABEL_AND = "labelAnd";
+
+    /**权重key*/
+    String WEIGHT_KEY = "weight";
+
+    /**删除*/
+    String STATUS_DEL = "1";
+
+    /**正常*/
+    String STATUS_NORMAL = "0";
+
+    /**锁定*/
+    String STATUS_LOCK = "9";
+
+    /**目录*/
+    Integer CATALOG = -1;
+
+    /**菜单*/
+    Integer MENU = 1;
+
+    /**权限*/
+    Integer PERMISSION = 2;
+
+    /**删除标记*/
+    String DEL_FLAG = "is_del";
+
+    /**超级管理员用户名*/
+    String ADMIN_USER_NAME = "admin";
+
+    /**公共日期格式*/
+    String MONTH_FORMAT = "yyyy-MM";
+    String DATE_FORMAT = "yyyy-MM-dd";
+    String DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
+    String SIMPLE_MONTH_FORMAT = "yyyyMM";
+    String SIMPLE_DATE_FORMAT = "yyyyMMdd";
+    String SIMPLE_DATETIME_FORMAT = "yyyyMMddHHmmss";
+
+    String DEF_USER_PASSWORD = "123456";
+
+    String LOCK_KEY_PREFIX = "LOCK_KEY:";
+
+    /**租户id参数*/
+    String TENANT_ID_PARAM = "tenantId";
+
+    /**负载均衡策略-版本号 信息头*/
+    String INTEGRATED_VERSION = "integrated-version";
+    String GROUP_CODE = "groupcode";
+    
+    /**注册中心元数据 版本号*/
+    String METADATA_VERSION = "version";
+	String DEFAULT_USER_ID = "systemId";
+	String DEFAULT_PROJECT_ID = "Pj1111111111";
+	
+}

+ 16 - 0
apm-redis/src/main/java/com/persagy/common/exception/LockException.java

@@ -0,0 +1,16 @@
+package com.persagy.common.exception;
+
+/**
+ * 分布式锁异常
+ *
+ * @description 
+ * @author persagy
+ * @since 2020年11月4日:	下午8:09:02
+ */
+public class LockException extends RuntimeException {
+    private static final long serialVersionUID = 6610083281801529147L;
+
+    public LockException(String message) {
+        super(message);
+    }
+}

+ 46 - 0
apm-redis/src/main/java/com/persagy/common/lock/DistributedLock.java

@@ -0,0 +1,46 @@
+package com.persagy.common.lock;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 分布式锁顶级接口
+ *
+ * @description 
+ * @author persagy
+ * @since 2020年11月4日:	下午8:09:02
+ */
+public interface DistributedLock {
+    /**
+     * 获取锁,如果获取不成功则一直等待直到lock被获取
+     * @param key 锁的key
+     * @param leaseTime 加锁的时间,超过这个时间后锁便自动解锁;
+     *                  如果leaseTime为-1,则保持锁定直到显式解锁
+     * @param unit {@code leaseTime} 参数的时间单位
+     * @param isFair 是否公平锁
+     * @return 锁对象
+     */
+    Object lock(String key, long leaseTime, TimeUnit unit, boolean isFair) throws Exception;
+    Object lock(String key, long leaseTime, TimeUnit unit) throws Exception;
+    Object lock(String key, boolean isFair) throws Exception;
+    Object lock(String key) throws Exception;
+
+    /**
+     * 尝试获取锁,如果锁不可用则等待最多waitTime时间后放弃
+     * @param key 锁的key
+     * @param waitTime 获取锁的最大尝试时间(单位 {@code unit})
+     * @param leaseTime 加锁的时间,超过这个时间后锁便自动解锁;
+     *                  如果leaseTime为-1,则保持锁定直到显式解锁
+     * @param unit {@code waitTime} 和 {@code leaseTime} 参数的时间单位
+     * @return 锁对象,如果获取锁失败则为null
+     */
+    Object tryLock(String key, long waitTime, long leaseTime, TimeUnit unit, boolean isFair) throws Exception;
+    Object tryLock(String key, long waitTime, long leaseTime, TimeUnit unit) throws Exception;
+    Object tryLock(String key, long waitTime, TimeUnit unit, boolean isFair) throws Exception;
+    Object tryLock(String key, long waitTime, TimeUnit unit) throws Exception;
+
+    /**
+     * 释放锁
+     * @param lock 锁对象
+     */
+    void unlock(Object lock) throws Exception;
+}

+ 74 - 0
apm-redis/src/main/java/com/persagy/common/lock/Lock.java

@@ -0,0 +1,74 @@
+package com.persagy.common.lock;
+
+
+import com.persagy.common.model.LockModel;
+
+import java.lang.annotation.*;
+
+/***
+ * @Description: 分布式锁的注解
+ * @author: lijie
+ * @Date:2020/8/18 9:49
+ * Update By lijie 2020/8/18 9:49
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface Lock {
+
+    /***
+     * @Description: 锁的模式:如果不设置,自动模式,当参数只有一个.使用 REENTRANT 参数多个 MULTIPLE
+     * @return : com.persagy.enums.LockModel{@link LockModel}
+     * @author: lijie
+     * @Date:2020/8/18 9:49
+     * Update By lijie 2020/8/18 9:49
+     */
+    LockModel lockModel() default LockModel.AUTO;
+
+    /***
+     * @Description: 如果keys有多个,如果不设置,则使用 联锁
+     * @return : java.lang.String[]
+     * @author: lijie
+     * @Date:2020/8/18 9:51
+     * Update By lijie 2020/8/18 9:51
+     */
+    String[] keys() default {};
+
+    /***
+     * @Description: key的静态常量:当key的spel的值是LIST,数组时使用+号连接将会被spel认为这个变量是个字符串,只能产生一把锁,
+     * 达不到我们的目的,而我们如果又需要一个常量的话.这个参数将会在拼接在每个元素的后面
+     * @return : java.lang.String
+     * @author: lijie
+     * @Date:2020/8/18 9:51
+     * Update By lijie 2020/8/18 9:51
+     */
+    String keyConstant() default "";
+
+    /***
+     * @Description: 锁超时时间,默认30000毫秒(可在配置文件全局设置)
+     * @return : long
+     * @author: lijie
+     * @Date:2020/8/18 9:51
+     * Update By lijie 2020/8/18 9:51
+     */
+    long lockWatchdogTimeout() default 0;
+
+    /***
+     * @Description: 等待加锁超时时间,默认10000毫秒 -1 则表示一直等待(可在配置文件全局设置)
+     * @return : long
+     * @author: lijie
+     * @Date:2020/8/18 9:52
+     * Update By lijie 2020/8/18 9:52
+     */
+    long attemptTimeout() default 0;
+    /***
+     * @Description: 加锁库的索引
+     * @return : int
+     * @author: lijie
+     * @Date:2020/8/18 9:52
+     * Update By lijie 2020/8/18 9:52
+     */
+    int databaseIndex() default 0;
+
+
+}

+ 21 - 0
apm-redis/src/main/java/com/persagy/common/model/LockModel.java

@@ -0,0 +1,21 @@
+package com.persagy.common.model;
+
+/**
+ * 锁的模式
+ */
+public enum LockModel {
+    //可重入锁
+    REENTRANT,
+    //公平锁
+    FAIR,
+    //联锁
+    MULTIPLE,
+    //红锁
+    REDLOCK,
+    //读锁
+    READ,
+    //写锁
+    WRITE,
+    //自动模式,当参数只有一个.使用 REENTRANT 参数多个 REDLOCK
+    AUTO
+}

+ 234 - 0
apm-redis/src/main/java/com/persagy/common/redis/aop/LockAop.java

@@ -0,0 +1,234 @@
+package com.persagy.common.redis.aop;
+
+import com.persagy.common.exception.LockException;
+import com.persagy.common.lock.Lock;
+import com.persagy.common.model.LockModel;
+import com.persagy.common.redis.boot.RedisBeanContext;
+import com.persagy.common.redis.properties.RedissonProperties;
+import lombok.extern.slf4j.Slf4j;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.redisson.RedissonMultiLock;
+import org.redisson.RedissonRedLock;
+import org.redisson.api.RLock;
+import org.redisson.api.RReadWriteLock;
+import org.redisson.api.RedissonClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
+import org.springframework.core.annotation.Order;
+import org.springframework.expression.EvaluationContext;
+import org.springframework.expression.Expression;
+import org.springframework.expression.ExpressionParser;
+import org.springframework.expression.spel.standard.SpelExpressionParser;
+import org.springframework.expression.spel.support.StandardEvaluationContext;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+
+/***
+ * @Description: 分布式锁aop
+ * @author: lijie
+ * @Date:2020/8/18 9:53
+ * Update By lijie 2020/8/18 9:53
+ */
+@Aspect
+@Order(-10)
+@Slf4j
+public class LockAop {
+    /**redis的属性*/
+    @Autowired
+    private RedissonProperties redissonProperties;
+
+    /***
+     * @Description: 通过spring Spel 获取参数
+     * @param key: 定义的key值 以#开头 例如:#user
+     * @param parameterNames: 形参
+     * @param values: 形参值
+     * @param keyConstant: key的常量
+     * @return : java.util.List<java.lang.String>
+     * @author: lijie
+     * @Date:2020/8/18 10:02
+     * Update By lijie 2020/8/18 10:02
+     */
+    public List<String> getVauleBySpel(String key, String[] parameterNames, Object[] values, String keyConstant) {
+        List<String> keys=new ArrayList<>();
+        if(!key.contains("#")){
+            String s = "redisson:lock:" + key+keyConstant;
+            log.info("没有使用spel表达式value->{}",s);
+            keys.add(s);
+            return keys;
+        }
+        //spel解析器
+        ExpressionParser parser = new SpelExpressionParser();
+        //spel上下文
+        EvaluationContext context = new StandardEvaluationContext();
+        for (int i = 0; i < parameterNames.length; i++) {
+            context.setVariable(parameterNames[i], values[i]);
+        }
+        Expression expression = parser.parseExpression(key);
+        Object value = expression.getValue(context);
+        if(value!=null){
+            if(value instanceof List){
+                List value1 = (List) value;
+                for (Object o : value1) {
+                    keys.add("redisson:lock:" + o.toString()+keyConstant);
+                }
+            }else if(value.getClass().isArray()){
+                Object[] obj= (Object[]) value;
+                for (Object o : obj) {
+                    keys.add("redisson:lock:" + o.toString()+keyConstant);
+                }
+            }else {
+                keys.add("redisson:lock:" + value.toString()+keyConstant);
+            }
+        }
+        log.info("spel表达式key={},value={}",key,keys);
+        return keys;
+    }
+    /***
+     * @Description: 环绕通知
+     * @param proceedingJoinPoint : 切入点
+     * @param lock : 锁对象
+     * @return : java.lang.Object
+     * @author: lijie
+     * @Date:2020/8/18 10:04
+     * Update By lijie 2020/8/18 10:04
+     */
+    @Around("@within(lock) || @annotation(lock)")
+    public Object aroundAdvice(ProceedingJoinPoint proceedingJoinPoint, Lock lock) throws Throwable {
+        // 1.获得锁的对象
+        String[] keys = lock.keys();
+        if (keys.length == 0) {
+            throw new RuntimeException("keys不能为空");
+        }
+        String[] parameterNames = new LocalVariableTableParameterNameDiscoverer().getParameterNames(((MethodSignature) proceedingJoinPoint.getSignature()).getMethod());
+        Object[] args = proceedingJoinPoint.getArgs();
+        // 1.1 等待加锁超时时间
+        long attemptTimeout = lock.attemptTimeout();
+        if (attemptTimeout == 0) {
+            attemptTimeout = redissonProperties.getAttemptTimeout();
+        }
+        // 1.2 锁超时时间
+        long lockWatchdogTimeout = lock.lockWatchdogTimeout();
+        if (lockWatchdogTimeout == 0) {
+            lockWatchdogTimeout = redissonProperties.getLockWatchdogTimeout();
+        }
+        // 1.3 锁的模式
+        LockModel lockModel = lock.lockModel();
+        if (lockModel.equals(LockModel.AUTO)) {
+            // 首先取配置的锁模式,取不到当多key时使用红锁,否则使用可重入锁
+            LockModel lockModel1 = redissonProperties.getLockModel();
+            if (lockModel1 != null) {
+                lockModel = lockModel1;
+            } else if (keys.length > 1) {
+                lockModel = LockModel.REDLOCK;
+            } else {
+                lockModel = LockModel.REENTRANT;
+            }
+        }
+        if (!lockModel.equals(LockModel.MULTIPLE) && !lockModel.equals(LockModel.REDLOCK) && keys.length > 1) {
+            throw new RuntimeException("参数有多个,锁模式为->" + lockModel.name() + ".无法锁定");
+        }
+        log.info("锁模式->{},等待锁定时间->{}秒.锁定最长时间->{}秒",lockModel.name(),attemptTimeout/1000,lockWatchdogTimeout/1000);
+        // 1.4 根据索引库索引获得redissonClient对象
+        int databaseIndex = lock.databaseIndex();
+        RedissonClient redissonClient = RedisBeanContext.getBeanByName(RedisBeanContext
+                .getRedissonClientBeanName(databaseIndex), RedissonClient.class);
+        boolean res = false;
+        RLock rLock = null;
+        // 2.根据不同模式获取锁.
+        switch (lockModel) {
+            // 公平锁
+            case FAIR:
+                rLock = redissonClient.getFairLock(getVauleBySpel(keys[0],parameterNames,args,lock.keyConstant()).get(0));
+                break;
+            // 红锁
+            case REDLOCK:
+                List<RLock> rLocks=new ArrayList<>();
+                for (String key : keys) {
+                    List<String> vauleBySpel = getVauleBySpel(key, parameterNames, args, lock.keyConstant());
+                    for (String s : vauleBySpel) {
+                        rLocks.add(redissonClient.getLock(s));
+                    }
+                }
+                RLock[] locks=new RLock[rLocks.size()];
+                int index=0;
+                for (RLock r : rLocks) {
+                    locks[index++]=r;
+                }
+                rLock = new RedissonRedLock(locks);
+                break;
+            // 联锁
+            case MULTIPLE:
+                rLocks=new ArrayList<>();
+
+                for (String key : keys) {
+                    List<String> vauleBySpel = getVauleBySpel(key, parameterNames, args, lock.keyConstant());
+                    for (String s : vauleBySpel) {
+                        rLocks.add(redissonClient.getLock(s));
+                    }
+                }
+                locks=new RLock[rLocks.size()];
+                index=0;
+                for (RLock r : rLocks) {
+                    locks[index++]=r;
+                }
+                rLock = new RedissonMultiLock(locks);
+                break;
+            // 可重入锁
+            case REENTRANT:
+                List<String> vauleBySpel = getVauleBySpel(keys[0], parameterNames, args, lock.keyConstant());
+                //如果spel表达式是数组或者LIST 则使用红锁
+                if(vauleBySpel.size()==1){
+                    rLock= redissonClient.getLock(vauleBySpel.get(0));
+                }else {
+                    locks=new RLock[vauleBySpel.size()];
+                    index=0;
+                    for (String s : vauleBySpel) {
+                        locks[index++]=redissonClient.getLock(s);
+                    }
+                    rLock = new RedissonRedLock(locks);
+                }
+                break;
+            // 读锁
+            case READ:
+                RReadWriteLock rwlock = redissonClient.getReadWriteLock(getVauleBySpel(keys[0],parameterNames,args, lock.keyConstant()).get(0));
+                rLock = rwlock.readLock();
+                break;
+            // 写锁
+            case WRITE:
+                RReadWriteLock rwlock1 = redissonClient.getReadWriteLock(getVauleBySpel(keys[0],parameterNames,args, lock.keyConstant()).get(0));
+                rLock = rwlock1.writeLock();
+                break;
+        }
+        // 3.执行aop
+        if(rLock!=null) {
+            try {
+                if (attemptTimeout == -1) {
+                    res = true;
+                    // 一直等待加锁
+                    rLock.lock(lockWatchdogTimeout, TimeUnit.MILLISECONDS);
+                } else {
+                    res = rLock.tryLock(attemptTimeout, lockWatchdogTimeout, TimeUnit.MILLISECONDS);
+                }
+                if (res) {
+                    Object obj = proceedingJoinPoint.proceed();
+                    return obj;
+                }else{
+                    throw new LockException("获取锁失败");
+                }
+            } finally {
+            	if (res) {
+            		rLock.unlock();
+            	}
+            }
+        }
+        throw new LockException("获取锁失败");
+    }
+
+
+}

+ 173 - 0
apm-redis/src/main/java/com/persagy/common/redis/base/HashOperations.java

@@ -0,0 +1,173 @@
+package com.persagy.common.redis.base;
+
+import java.util.List;
+import java.util.Map;
+
+/***
+ * @Description: Hash类型的操作
+ * @author: lijie
+ * @Date:2020/9/17 9:30
+ * Update By lijie 2020/9/17 9:30
+ */
+public interface HashOperations {
+
+    /***
+     * @Description: hash类型存储数据
+     * @param databaseIndex : 库索引
+     * @param key : redis#key
+     * @param field : hash#key
+     * @param value : 字段值
+     * @return : void
+     * @author: lijie
+     * @Date:2020/8/18 11:07
+     * Update By lijie 2020/8/18 11:07
+     */
+    void hset(Integer databaseIndex, String key, String field, String value);
+
+    /***
+     * @Description: hash类型存储数据
+     * @param key : redis#key
+     * @param field : hash#key
+     * @param value : 字段值
+     * @return : void
+     * @author: lijie
+     * @Date:2020/8/18 11:07
+     * Update By lijie 2020/8/18 11:07
+     */
+    void hset(String key, String field, String value);
+
+    /***
+     * @Description: hash类型获取数据
+     * @param databaseIndex : 库索引
+     * @param key : redis#key
+     * @param field : hash#key
+     * @return : java.lang.String
+     * @author: lijie
+     * @Date:2020/8/18 11:07
+     * Update By lijie 2020/8/18 11:07
+     */
+    String hget(Integer databaseIndex, String key, String field);
+
+    /***
+     * @Description: hash类型获取数据
+     * @param key : redis#key
+     * @param field : hash#key
+     * @return : java.lang.String
+     * @author: lijie
+     * @Date:2020/8/18 11:07
+     * Update By lijie 2020/8/18 11:07
+     */
+    String hget(String key, String field);
+
+    /***
+     * @Description: hash类型删除数据
+     * @param databaseIndex : 库索引
+     * @param key : redis#key
+     * @param field : hash#key
+     * @return : java.lang.Long
+     * @author: lijie
+     * @Date:2020/8/18 11:07
+     * Update By lijie 2020/8/18 11:07
+     */
+    Long hdel(Integer databaseIndex, String key, String field);
+
+    /***
+     * @Description: hash类型删除数据
+     * @param key : redis#key
+     * @param field : hash#key
+     * @return : java.lang.Long
+     * @author: lijie
+     * @Date:2020/8/18 11:07
+     * Update By lijie 2020/8/18 11:07
+     */
+    Long hdel(String key, String field);
+
+    /***
+     * @Description: hash类型批量添加
+     * @param databaseIndex : 库索引
+     * @param key : redis#key
+     * @param map : hashMap对象
+     * @return : void
+     * @author: lijie
+     * @Date:2020/8/18 11:07
+     * Update By lijie 2020/8/18 11:07
+     */
+    void hmset(Integer databaseIndex, String key, Map<String, String> map);
+
+    /***
+     * @Description: hash类型批量添加
+     * @param key : redis#key
+     * @param map : hashMap对象
+     * @return : void
+     * @author: lijie
+     * @Date:2020/8/18 11:07
+     * Update By lijie 2020/8/18 11:07
+     */
+    void hmset(String key, Map<String, String> map);
+
+    /***
+     * @Description: hash类型批量添加
+     * @param databaseIndex : 库索引
+     * @param key : redis#key
+     * @param fields : hash#key数组
+     * @return : java.util.List<java.lang.String>
+     * @author: lijie
+     * @Date:2020/8/18 11:07
+     * Update By lijie 2020/8/18 11:07
+     */
+    List<String> hmget(Integer databaseIndex, String key, String... fields);
+
+    /***
+     * @Description: hash类型批量添加
+     * @param key : redis#key
+     * @param fields : hash#key数组
+     * @return : java.util.List<java.lang.String>
+     * @author: lijie
+     * @Date:2020/8/18 11:07
+     * Update By lijie 2020/8/18 11:07
+     */
+    List<String> hmget(String key, String... fields);
+
+    /***
+     * @Description: hash类型获取属性个数
+     * @param databaseIndex : 库索引
+     * @param key : redis#key
+     * @return : java.lang.Long
+     * @author: lijie
+     * @Date:2020/8/18 11:07
+     * Update By lijie 2020/8/18 11:07
+     */
+    Long hlen(Integer databaseIndex, String key);
+
+    /***
+     * @Description: hash类型获取属性个数
+     * @param key : redis#key
+     * @return : java.lang.Long
+     * @author: lijie
+     * @Date:2020/8/18 11:07
+     * Update By lijie 2020/8/18 11:07
+     */
+    Long hlen(String key);
+
+    /***
+     * @Description: hash类型获取所有属性
+     * @param databaseIndex : 库索引
+     * @param key : redis#key
+     * @return : java.util.Map<java.lang.String,java.lang.String>
+     * @author: lijie
+     * @Date:2020/8/18 11:07
+     * Update By lijie 2020/8/18 11:07
+     */
+    Map<String, String> hgetAll(Integer databaseIndex, String key);
+
+    /***
+     * @Description: hash类型获取所有属性
+     * @param key : redis#key
+     * @return : java.util.Map<java.lang.String,java.lang.String>
+     * @author: lijie
+     * @Date:2020/8/18 11:07
+     * Update By lijie 2020/8/18 11:07
+     */
+    Map<String, String> hgetAll(String key);
+
+}

+ 138 - 0
apm-redis/src/main/java/com/persagy/common/redis/base/KeyOperations.java

@@ -0,0 +1,138 @@
+package com.persagy.common.redis.base;
+
+import java.util.Set;
+
+/***
+ * @Description: redis相关的key操作
+ * @author: lijie
+ * @Date:2020/9/17 9:23
+ * Update By lijie 2020/9/17 9:23
+ */
+public interface KeyOperations {
+    /***
+     * @Description: 判断redis#key键是否存在
+     * @param databaseIndex : 索引库
+     * @param key : key
+     * @return : boolean
+     * @author: lijie
+     * @Date:2020/8/18 9:47
+     * Update By lijie 2020/8/18 9:47
+     */
+    Boolean exists(Integer databaseIndex, String key);
+
+    /***
+     * @Description: 判断redis#key键是否存在
+     * @param key : key
+     * @return : boolean
+     * @author: lijie
+     * @Date:2020/8/18 10:42
+     * Update By lijie 2020/8/18 10:42
+     */
+    Boolean exists(String key);
+
+    /***
+     * @Description: 正则获取key
+     * @param index : 游标
+     * @param regx : 正则表达式
+     * @return : java.util.Set<java.lang.String>
+     * @author: lijie
+     * @Date:2020/8/18 10:51
+     * Update By lijie 2020/8/18 10:51
+     */
+    Set<String> scan(int index, String regx);
+
+    /***
+     * @Description: 正则获取key
+     * @param regx : 正则表达式
+     * @return : java.util.Set<java.lang.String>
+     * @author: lijie
+     * @Date:2020/8/18 10:51
+     * Update By lijie 2020/8/18 10:51
+     */
+    Set<String> scan(String regx);
+
+    /***
+     * @Description: 获取redis#key过期时间
+     * @param key : redis#key
+     * @return : java.lang.Long
+     * @author: lijie
+     * @Date:2020/8/18 11:03
+     * Update By lijie 2020/8/18 11:03
+     */
+    Long getTtl(Integer databaseIndex, String key);
+
+    /***
+     * @Description: 获取redis#key过期时间
+     * @param key : redis#key
+     * @return : java.lang.Long
+     * @author: lijie
+     * @Date:2020/8/18 11:03
+     * Update By lijie 2020/8/18 11:03
+     */
+    Long getTtl(String key);
+
+    /***
+     * @Description: 设置key的过期时间
+     * @param databaseIndex : 库索引
+     * @param key : redis#key
+     * @param seconds : 过期时间单位(S)
+     * @return : void
+     * @author: lijie
+     * @Date:2020/8/18 11:14
+     * Update By lijie 2020/8/18 11:14
+     */
+    void setTtl(Integer databaseIndex, String key, int seconds);
+
+    /***
+     * @Description: 设置key的过期时间
+     * @param key : redis#key
+     * @param seconds : 过期时间单位(S)
+     * @return : void
+     * @author: lijie
+     * @Date:2020/8/18 11:14
+     * Update By lijie 2020/8/18 11:14
+     */
+    void setTtl(String key, int seconds);
+
+    /***
+     * @Description: 删除redis#key过期时间
+     * @param databaseIndex : 库索引
+     * @param key : redis#key
+     * @return : java.lang.Long
+     * @author: lijie
+     * @Date:2020/8/18 11:03
+     * Update By lijie 2020/8/18 11:03
+     */
+    Boolean removeTtl(Integer databaseIndex, String key);
+
+    /***
+     * @Description: 删除redis#key过期时间
+     * @param key : redis#key
+     * @return : java.lang.Long
+     * @author: lijie
+     * @Date:2020/8/18 11:03
+     * Update By lijie 2020/8/18 11:03
+     */
+    Boolean removeTtl(String key);
+
+    /***
+     * @Description: 删除redis#key
+     * @param key : redis#key
+     * @return : java.lang.Long
+     * @author: lijie
+     * @Date:2020/8/18 11:03
+     * Update By lijie 2020/8/18 11:03
+     */
+    Boolean delete(String key);
+
+    /***
+     * @Description: 删除redis#key
+     * @param databaseIndex : 库索引
+     * @param key : redis#key
+     * @return : java.lang.Long
+     * @author: lijie
+     * @Date:2020/8/18 11:03
+     * Update By lijie 2020/8/18 11:03
+     */
+    Boolean delete(Integer databaseIndex, String key);
+}

+ 191 - 0
apm-redis/src/main/java/com/persagy/common/redis/base/ListOperations.java

@@ -0,0 +1,191 @@
+package com.persagy.common.redis.base;
+
+import java.util.List;
+
+/***
+ * @Description: List类型的操作命令
+ * @author: lijie
+ * @Date:2020/9/17 9:32
+ * Update By lijie 2020/9/17 9:32
+ */
+public interface ListOperations {
+
+    /***
+     * @Description:  从左边入列表
+     * @param databaseIndex : 库索引
+     * @param key : redis#key
+     * @param values : 入列表的值
+     * @return : void
+     * @author: lijie
+     * @Date:2020/8/18 11:15
+     * Update By lijie 2020/8/18 11:15
+     */
+    void lpush(Integer databaseIndex, String key, String... values);
+
+    /***
+     * @Description:  从左边入列表
+     * @param key : redis#key
+     * @param values : 入列表的值
+     * @return : void
+     * @author: lijie
+     * @Date:2020/8/18 11:15
+     * Update By lijie 2020/8/18 11:15
+     */
+    void lpush(String key, String... values);
+
+    /***
+     * @Description:  从右边入列表
+     * @param databaseIndex : 库索引
+     * @param key : redis#key
+     * @param values : 入列表的值
+     * @return : void
+     * @author: lijie
+     * @Date:2020/8/18 11:15
+     * Update By lijie 2020/8/18 11:15
+     */
+    void rpush(Integer databaseIndex, String key, String... values);
+
+    /***
+     * @Description:  从右边入列表
+     * @param key : redis#key
+     * @param values : 入列表的值
+     * @return : void
+     * @author: lijie
+     * @Date:2020/8/18 11:15
+     * Update By lijie 2020/8/18 11:15
+     */
+    void rpush(String key, String... values);
+
+    /***
+     * @Description:  返回列表长度
+     * @param databaseIndex : 库索引
+     * @param key : redis#key
+     * @return : java.lang.Long
+     * @author: lijie
+     * @Date:2020/8/18 11:15
+     * Update By lijie 2020/8/18 11:15
+     */
+    Long llen(Integer databaseIndex, String key);
+
+    /***
+     * @Description:  返回列表长度
+     * @param key : redis#key
+     * @return : java.lang.Long
+     * @author: lijie
+     * @Date:2020/8/18 11:15
+     * Update By lijie 2020/8/18 11:15
+     */
+    Long llen(String key);
+
+    /***
+     * @Description:  返回index下标的元素
+     * @param databaseIndex : 库索引
+     * @param key : redis#key
+     * @param index : 下标
+     * @return : java.lang.String
+     * @author: lijie
+     * @Date:2020/8/18 11:15
+     * Update By lijie 2020/8/18 11:15
+     */
+    String lindex(Integer databaseIndex, String key, long index);
+
+    /***
+     * @Description:  返回index下标的元素
+     * @param key : redis#key
+     * @param index : 下标
+     * @return : java.lang.String
+     * @author: lijie
+     * @Date:2020/8/18 11:15
+     * Update By lijie 2020/8/18 11:15
+     */
+    String lindex(String key, long index);
+
+    /***
+     * @Description:  获取key列表所有元素
+     * @param databaseIndex : 库索引
+     * @param key : redis#key
+     * @return : java.util.List<java.lang.String>
+     * @author: lijie
+     * @Date:2020/8/18 11:15
+     * Update By lijie 2020/8/18 11:15
+     */
+    List<String> lrangeAll(Integer databaseIndex, String key);
+
+    /***
+     * @Description:  获取key列表所有元素
+     * @param key : redis#key
+     * @return : java.util.List<java.lang.String>
+     * @author: lijie
+     * @Date:2020/8/18 11:15
+     * Update By lijie 2020/8/18 11:15
+     */
+    List<String> lrangeAll(String key);
+
+    /***
+     * @Description:  获取列表指定范围的元素
+     * @param databaseIndex : 库索引
+     * @param key : redis#key
+     * @param start: 开始位置
+     * @param end: 结束位置
+     * @return : java.util.List<java.lang.String>
+     * @author: lijie
+     * @Date:2020/8/18 11:15
+     * Update By lijie 2020/8/18 11:15
+     */
+    List<String> lrange(Integer databaseIndex, String key, long start, long end);
+
+    /***
+     * @Description:  获取列表指定范围的元素
+     * @param key : redis#key
+     * @param start: 开始位置
+     * @param end: 结束位置
+     * @return : java.util.List<java.lang.String>
+     * @author: lijie
+     * @Date:2020/8/18 11:15
+     * Update By lijie 2020/8/18 11:15
+     */
+    List<String> lrange(String key, long start, long end);
+
+    /***
+     * @Description:  弹出列表头部元素
+     * @param databaseIndex : 库索引
+     * @param key : redis#key
+     * @return : java.lang.String
+     * @author: lijie
+     * @Date:2020/8/18 11:15
+     * Update By lijie 2020/8/18 11:15
+     */
+    String lpop(Integer databaseIndex, String key);
+
+    /***
+     * @Description:  弹出列表头部元素
+     * @param key : redis#key
+     * @return : java.lang.String
+     * @author: lijie
+     * @Date:2020/8/18 11:15
+     * Update By lijie 2020/8/18 11:15
+     */
+    String lpop(String key);
+
+    /***
+     * @Description:  弹出列表尾部元素
+     * @param databaseIndex : 库索引
+     * @param key : redis#key
+     * @return : java.lang.String
+     * @author: lijie
+     * @Date:2020/8/18 11:15
+     * Update By lijie 2020/8/18 11:15
+     */
+    String rpop(Integer databaseIndex, String key);
+
+    /***
+     * @Description:  弹出列表尾部元素
+     * @param key : redis#key
+     * @return : java.lang.String
+     * @author: lijie
+     * @Date:2020/8/18 11:15
+     * Update By lijie 2020/8/18 11:15
+     */
+    String rpop(String key);
+
+}

+ 78 - 0
apm-redis/src/main/java/com/persagy/common/redis/base/RedissonTemplate.java

@@ -0,0 +1,78 @@
+package com.persagy.common.redis.base;
+
+import com.persagy.common.lock.DistributedLock;
+
+/**
+ * redis 操作函数顶级接口
+ */
+public interface RedissonTemplate extends KeyOperations, StringOperations, HashOperations, ListOperations, DistributedLock {
+
+    /***
+     * @Description:  分布式锁-锁定
+     * @param databaseIndex : 库索引
+     * @param key: 分布式锁Key
+     * @param value: 分布式锁value
+     * @param expire: 分布式锁过期时间
+     * @return : true-加锁成功/false-加锁失败
+     * @author: lijie
+     * @Date:2020/8/18 11:15
+     * Update By lijie 2020/8/18 11:15
+     */
+    Boolean tryLock(Integer databaseIndex, String key, String value, long expire);
+
+    /***
+     * @Description:  分布式锁-锁定
+     * @param key: 分布式锁Key
+     * @param value: 分布式锁value
+     * @param expire: 分布式锁过期时间
+     * @return : true-加锁成功/false-加锁失败
+     * @author: lijie
+     * @Date:2020/8/18 11:15
+     * Update By lijie 2020/8/18 11:15
+     */
+    Boolean tryLock(String key, String value, long expire);
+
+    /***
+     * @Description:  分布式锁-解锁
+     * @param databaseIndex: 库索引
+     * @param key: 分布式锁Key
+     * @param value: 分布式锁value
+     * @return : true-解除锁成功/false-解除锁失败
+     * @author: lijie
+     * @Date:2020/8/18 11:15
+     * Update By lijie 2020/8/18 11:15
+     */
+    Boolean unLock(Integer databaseIndex, String key, String value);
+
+    /***
+     * @Description:  分布式锁-解锁
+     * @param key: 分布式锁Key
+     * @param value: 分布式锁value
+     * @return : true-解除锁成功/false-解除锁失败
+     * @author: lijie
+     * @Date:2020/8/18 11:15
+     * Update By lijie 2020/8/18 11:15
+     */
+    Boolean unLock(String key, String value);
+    
+    /**
+     * redis 分布式锁-锁定
+     *
+     * @param key          分布式等待锁Key
+     * @param expireSecond 持有锁超时毫秒数
+     * @param waitSecond   等待锁超时秒数
+     * @param flag         线程标识
+     * @return true-获取锁成功/false-获取锁失败
+     */
+    //boolean tryLockWait(String key, long expireSecond, int waitSecond, String flag);
+
+    /**
+     * redis 分布式锁-解锁
+     *
+     * @param key  分布式等待锁Key
+     * @param flag 线程标识
+     * @return true-解除锁成功/false-解除锁失败
+     */
+    // boolean unlockWait(String key, String flag);
+
+}

+ 207 - 0
apm-redis/src/main/java/com/persagy/common/redis/base/StringOperations.java

@@ -0,0 +1,207 @@
+package com.persagy.common.redis.base;
+
+import java.util.List;
+
+/***
+ * @Description: redis的String类型的相关操作
+ * @author: lijie
+ * @Date:2020/9/17 9:28
+ * Update By lijie 2020/9/17 9:28
+ */
+public interface StringOperations {
+
+    /***
+     * @Description: 通过redis#key判断value长度
+     * @param databaseIndex : 库索引
+     * @param key : key
+     * @return : java.lang.Long
+     * @author: lijie
+     * @Date:2020/8/18 10:43
+     * Update By lijie 2020/8/18 10:43
+     */
+    Long length(Integer databaseIndex, String key);
+
+    /***
+     * @Description: 通过redis#key判断value长度
+     * @param key : key
+     * @return : java.lang.Long
+     * @author: lijie
+     * @Date:2020/8/18 10:43
+     * Update By lijie 2020/8/18 10:43
+     */
+    Long length(String key);
+
+    /***
+     * @Description: 添加对象
+     * @param key : key
+     * @param obj : 值对象
+     * @return : void
+     * @author: lijie
+     * @Date:2020/8/18 10:45
+     * Update By lijie 2020/8/18 10:45
+     */
+    void setObj(String key, Object obj);
+
+    /***
+     * @Description: 添加对象
+     * @param databaseIndex : 库索引
+     * @param key : key
+     * @param obj : 值对象
+     * @return : void
+     * @author: lijie
+     * @Date:2020/8/18 10:45
+     * Update By lijie 2020/8/18 10:45
+     */
+    void setObj(Integer databaseIndex, String key, Object obj);
+
+    /***
+     * @Description: 添加字符串对象
+     * @param key : key
+     * @param value : 值
+     * @return : void
+     * @author: lijie
+     * @Date:2020/8/18 10:45
+     * Update By lijie 2020/8/18 10:45
+     */
+    void set(String key, String value);
+    /***
+     * @Description: 添加字符串对象
+     * @param databaseIndex : 库索引
+     * @param key : key
+     * @param value : 值
+     * @return : void
+     * @author: lijie
+     * @Date:2020/8/18 10:45
+     * Update By lijie 2020/8/18 10:45
+     */
+    void set(Integer databaseIndex, String key, String value);
+
+    /***
+     * @Description: 添加并设置过期时间
+     * @param key : redis#key
+     * @param value : 字符串对象
+     * @param seconds : 过期时间单位(S)
+     * @return : void
+     * @author: lijie
+     * @Date:2020/8/18 10:46
+     * Update By lijie 2020/8/18 10:46
+     */
+    void setex(String key, String value, int seconds);
+
+    /***
+     * @Description: 添加并设置过期时间
+     * @param databaseIndex : 库索引
+     * @param key : redis#key
+     * @param value : 字符串对象
+     * @param seconds : 过期时间单位(S)
+     * @return : void
+     * @author: lijie
+     * @Date:2020/8/18 10:46
+     * Update By lijie 2020/8/18 10:46
+     */
+    void setex(Integer databaseIndex, String key, String value, int seconds);
+
+
+    /***
+     * @Description: 添加并设置过期时间
+     * @param databaseIndex : 库索引
+     * @param key : redis#key
+     * @param obj : 对象
+     * @param seconds : 过期时间单位(S)
+     * @return : void
+     * @author: lijie
+     * @Date:2020/8/18 10:46
+     * Update By lijie 2020/8/18 10:46
+     */
+    void setexObj(Integer databaseIndex, String key, Object obj, int seconds);
+
+    /***
+     * @Description: 通过key获取值
+     * @param key : key
+     * @return : java.lang.String
+     * @author: lijie
+     * @Date:2020/8/18 10:47
+     * Update By lijie 2020/8/18 10:47
+     */
+    String get(String key);
+
+    /***
+     * @Description: 通过key获取值
+     * @param databaseIndex : 库索引
+     * @param key : key
+     * @return : java.lang.String
+     * @author: lijie
+     * @Date:2020/8/18 10:47
+     * Update By lijie 2020/8/18 10:47
+     */
+    String get(Integer databaseIndex, String key);
+
+    /***
+     * @Description: 获取多个redis#key的值
+     * @param keys : redis#key数组
+     * @return : java.util.List<java.lang.String>
+     * @author: lijie
+     * @Date:2020/8/18 10:49
+     * Update By lijie 2020/8/18 10:49
+     */
+    List<String> get(String... keys);
+
+    /***
+     * @Description: 获取多个redis#key的值
+     * @param databaseIndex : 库索引
+     * @param keys : redis#key数组
+     * @return : java.util.List<java.lang.String>
+     * @author: lijie
+     * @Date:2020/8/18 10:49
+     * Update By lijie 2020/8/18 10:49
+     */
+    List<String> get(Integer databaseIndex, String... keys);
+
+    /***
+     * @Description: 获取 redis#key值并转换为目标对象
+     * @param key   redis#key
+     * @param clazz 目标对象
+     * @param <T>   对象类型
+     * @return : T
+     * @author: lijie
+     * @Date:2020/8/18 10:58
+     * Update By lijie 2020/8/18 10:58
+     */
+    <T> T getObj(String key, Class<T> clazz);
+
+    /***
+     * @Description: 获取 redis#key值并转换为目标对象
+     * @param databaseIndex: 库索引
+     * @param key: redis#key
+     * @param clazz: 目标对象
+     * @param <T>:  对象类型
+     * @return : T
+     * @author: lijie
+     * @Date:2020/8/18 10:58
+     * Update By lijie 2020/8/18 10:58
+     */
+    <T> T getObj(Integer databaseIndex, String key, Class<T> clazz);
+
+    /***
+     * @Description: redis#key的值自增1
+     * @param databaseIndex : 库索引
+     * @param key : redis#key
+     * @return : java.lang.Long
+     * @author: lijie
+     * @Date:2020/8/18 11:05
+     * Update By lijie 2020/8/18 11:05
+     */
+    Long incr(Integer databaseIndex, String key);
+
+    /***
+     * @Description: redis#key的值自增1
+     * @param key : redis#key
+     * @return : java.lang.Long
+     * @author: lijie
+     * @Date:2020/8/18 11:05
+     * Update By lijie 2020/8/18 11:05
+     */
+    Long incr(String key);
+
+
+}

+ 239 - 0
apm-redis/src/main/java/com/persagy/common/redis/boot/RedisBeanContext.java

@@ -0,0 +1,239 @@
+package com.persagy.common.redis.boot;
+
+import org.redisson.api.RedissonClient;
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.data.redis.core.RedisTemplate;
+
+import java.lang.annotation.Annotation;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 上下文
+ *
+ */
+public class RedisBeanContext implements ApplicationContextAware {
+
+    /**
+     * 上下文
+     */
+    private static ApplicationContext applicationContext;
+
+    /**
+     * 默认构造方法,注入上下文,
+     * implements ApplicationContextAware 自动调用
+     *
+     * @param applicationContext
+     * @return
+     */
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+        RedisBeanContext.applicationContext = applicationContext;
+    }
+
+    /**
+     * 获取 bean
+     *
+     * @param clazz
+     * @return
+     */
+
+    public static <T> T getBean(Class<T> clazz) {
+        T obj;
+        try {
+            //从上下文获取 bean
+            obj = applicationContext.getBean(clazz);
+        } catch (Exception e) {
+            obj = null;
+        }
+        //返回 bean
+        return obj;
+    }
+    /**
+     * 获取 bean
+     *
+     * @return
+     */
+
+    public static <T> T getBeanByName(String clazzName, Class<T> clazz) {
+        T obj;
+        try {
+            //从上下文获取 bean
+            obj = (T) applicationContext.getBean(clazzName);
+        } catch (Exception e) {
+            obj = null;
+        }
+        //返回 bean
+        return obj;
+    }
+
+
+    /**
+     * 获取 bean 的类型
+     *
+     * @param clazz
+     * @return
+     * @time 2018/5/28 14:03
+     */
+    public static <T> List<T> getBeansOfType(Class<T> clazz) {
+        //声明一个结果
+        Map<String, T> map;
+        try {
+            //获取类型
+            map = applicationContext.getBeansOfType(clazz);
+        } catch (Exception e) {
+            map = null;
+        }
+        //返回 bean 的类型
+        return map == null ? null : new ArrayList<>(map.values());
+    }
+
+
+    /**
+     * 获取所有被注解的 bean
+     *
+     * @return
+     */
+    public static Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotation) {
+        Map<String, Object> map;
+        try {
+            //获取注解的 bean
+            map = applicationContext.getBeansWithAnnotation(annotation);
+        } catch (Exception e) {
+            map = null;
+        }
+        return map;
+    }
+
+    /***
+     * @Description: 获得redissonCliet对象Bean名称
+     * @param databaseIndex : 数据库索引
+     * @return : java.lang.Integer
+     * @author: lijie
+     * @Date:2020/8/17 9:58
+     * Update By lijie 2020/8/17 9:58
+     */
+    public static String getRedissonClientBeanName(Integer databaseIndex){
+    	return "redissonClient";
+        /*switch (databaseIndex){
+            case 0:
+                return "redissonClient";
+            case 1:
+                return "redissonClientOne";
+            case 2:
+                return "redissonClientTwo";
+            case 3:
+                return "redissonClientThree";
+            case 4:
+                return "redissonClientFour";
+            case 5:
+                return "redissonClientFive";
+            case 6:
+                return "redissonClientSix";
+            case 7:
+                return "redissonClientSeven";
+            case 8:
+                return "redissonClientEight";
+            case 9:
+                return "redissonClientNine";
+            case 10:
+                return "redissonClientTen";
+            case 11:
+                return "redissonClientEleven";
+            case 12:
+                return "redissonClientTwelve";
+            case 13:
+                return "redissonClientThirteen";
+            case 14:
+                return "redissonClientFourteen";
+            case 15:
+                return "redissonClientFifteen";
+            default:
+                return "redissonClient";
+        }*/
+    }
+    /***
+     * @Description: 获取redisTemplate对象
+      * @param databaseIndex : 库索引
+      * @return : org.springframework.data.redis.core.RedisTemplate
+     * @author: lijie
+     * @Date:2020/8/18 11:48
+     * Update By lijie 2020/8/18 11:48
+     */
+    /*public static StringRedisTemplate getStringRedisTemplate(Integer databaseIndex){
+        return RedisBeanContext.getBeanByName(RedisBeanContext.getStringRedisTemplateBeanName(databaseIndex), StringRedisTemplate.class);
+    }*/
+    /***
+     * @Description: 获取redisTemplate对象
+      * @param databaseIndex : 库索引
+      * @return : org.springframework.data.redis.core.RedisTemplate
+     * @author: lijie
+     * @Date:2020/8/18 11:48
+     * Update By lijie 2020/8/18 11:48
+     */
+    public static <T, R> RedisTemplate<T, R> getRedisTemplate(Integer databaseIndex){
+        return RedisBeanContext.getBeanByName(RedisBeanContext.getRedisTemplateBeanName(databaseIndex), RedisTemplate.class);
+    }
+    /***
+     * @Description: 获取redisTemplate对象
+      * @param databaseIndex : 库索引
+      * @return : org.springframework.data.redis.core.RedisTemplate
+     * @author: lijie
+     * @Date:2020/8/18 11:48
+     * Update By lijie 2020/8/18 11:48
+     */
+    public static RedissonClient getRedissonClient(Integer databaseIndex){
+        return RedisBeanContext.getBeanByName(RedisBeanContext.getRedissonClientBeanName(databaseIndex), RedissonClient.class);
+    }
+
+    /***
+     * @Description: 获得redisTemplate对象
+     * @param databaseIndex : 数据库索引
+     * @return : java.lang.Integer
+     * @author: lijie
+     * @Date:2020/8/17 9:58
+     * Update By lijie 2020/8/17 9:58
+     */
+    public static String getRedisTemplateBeanName(Integer databaseIndex){
+    	return "redisTemplate";
+        /*switch (databaseIndex){
+            case 0:
+                return "redisTemplate";
+            case 1:
+                return "redisTemplateOne";
+            case 2:
+                return "redisTemplateTwo";
+            case 3:
+                return "redisTemplateThree";
+            case 4:
+                return "redisTemplateFour";
+            case 5:
+                return "redisTemplateFive";
+            case 6:
+                return "redisTemplateSix";
+            case 7:
+                return "redisTemplateSeven";
+            case 8:
+                return "redisTemplateEight";
+            case 9:
+                return "redisTemplateNine";
+            case 10:
+                return "redisTemplateTen";
+            case 11:
+                return "redisTemplateEleven";
+            case 12:
+                return "redisTemplateTwelve";
+            case 13:
+                return "redisTemplateThirteen";
+            case 14:
+                return "redisTemplateFourteen";
+            case 15:
+                return "redisTemplateFifteen";
+            default:
+                return "redisTemplate";
+        }*/
+    }
+}

+ 27 - 0
apm-redis/src/main/java/com/persagy/common/redis/constant/RedisToolsConstant.java

@@ -0,0 +1,27 @@
+package com.persagy.common.redis.constant;
+
+/**
+ * redis 工具常量
+ *
+ * @author zlt
+ * @date 2018/5/21 11:59
+ */
+public class RedisToolsConstant {
+    private RedisToolsConstant() {
+        throw new IllegalStateException("Utility class");
+    }
+    /**
+     * single Redis
+     */
+    public final static int SINGLE = 1 ;
+
+    /**
+     * Redis cluster
+     */
+    public final static int CLUSTER = 2 ;
+    
+    /**
+     * redis连接地址前缀
+     */
+    public final static String REDIS_ADDRESS_PREFIX = "redis://";
+}

+ 106 - 0
apm-redis/src/main/java/com/persagy/common/redis/factory/ClusterRedissionConfig.java

@@ -0,0 +1,106 @@
+package com.persagy.common.redis.factory;
+
+import com.persagy.common.redis.properties.MultipleServerConfig;
+import com.persagy.common.redis.properties.RedissonProperties;
+import org.redisson.Redisson;
+import org.redisson.api.RedissonClient;
+import org.redisson.client.codec.Codec;
+import org.redisson.config.ClusterServersConfig;
+import org.redisson.config.Config;
+import org.redisson.connection.balancer.LoadBalancer;
+
+/**
+ * @version
+ * @description
+ * @company persagy
+ * @author zhangqiankun
+ * @since 2020年10月14日: 下午3:09:49
+ */
+public class ClusterRedissionConfig {
+
+	public static RedissonClient redissonClient(RedissonProperties redissonProperties) {
+		return Redisson.create(initConfig(redissonProperties));
+	}
+
+	private static Config initConfig(RedissonProperties redissonProperties) {
+		Config config = new Config();
+		try {
+			config.setCodec((Codec) Class.forName(redissonProperties.getCodec().getCodecType()).newInstance());
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+		config.setTransportMode(redissonProperties.getTransportMode());
+		if (redissonProperties.getThreads() != null) {
+			config.setThreads(redissonProperties.getThreads());
+		}
+		if (redissonProperties.getNettyThreads() != null) {
+			config.setNettyThreads(redissonProperties.getNettyThreads());
+		}
+		config.setReferenceEnabled(redissonProperties.getReferenceEnabled());
+		config.setLockWatchdogTimeout(redissonProperties.getLockWatchdogTimeout());
+		config.setKeepPubSubOrder(redissonProperties.getKeepPubSubOrder());
+		config.setUseScriptCache(redissonProperties.getUseScriptCache());
+		config.setMinCleanUpDelay(redissonProperties.getMinCleanUpDelay());
+		config.setMaxCleanUpDelay(redissonProperties.getMaxCleanUpDelay());
+
+		MultipleServerConfig multipleServerConfig = redissonProperties.getMultipleServerConfig();
+
+		ClusterServersConfig clusterServersConfig = config.useClusterServers();
+		clusterServersConfig.setScanInterval(multipleServerConfig.getScanInterval());
+		clusterServersConfig
+				.setSlaveConnectionMinimumIdleSize(multipleServerConfig.getSlaveConnectionMinimumIdleSize());
+		clusterServersConfig.setSlaveConnectionPoolSize(multipleServerConfig.getSlaveConnectionPoolSize());
+		clusterServersConfig
+				.setFailedSlaveReconnectionInterval(multipleServerConfig.getFailedSlaveReconnectionInterval());
+		clusterServersConfig.setFailedSlaveCheckInterval(multipleServerConfig.getFailedSlaveCheckInterval());
+		clusterServersConfig
+				.setMasterConnectionMinimumIdleSize(multipleServerConfig.getMasterConnectionMinimumIdleSize());
+		clusterServersConfig.setMasterConnectionPoolSize(multipleServerConfig.getMasterConnectionPoolSize());
+		clusterServersConfig.setReadMode(multipleServerConfig.getReadMode());
+		clusterServersConfig.setSubscriptionMode(multipleServerConfig.getSubscriptionMode());
+		clusterServersConfig.setSubscriptionConnectionMinimumIdleSize(
+				multipleServerConfig.getSubscriptionConnectionMinimumIdleSize());
+		clusterServersConfig
+				.setSubscriptionConnectionPoolSize(multipleServerConfig.getSubscriptionConnectionPoolSize());
+		clusterServersConfig.setDnsMonitoringInterval(multipleServerConfig.getDnsMonitoringInterval());
+		try {
+			clusterServersConfig.setLoadBalancer(
+					(LoadBalancer) Class.forName(multipleServerConfig.getLoadBalancer()).newInstance());
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+		for (String nodeAddress : multipleServerConfig.getNodeAddresses()) {
+			clusterServersConfig.addNodeAddress(RedissonClientFactory.prefixAddress(nodeAddress));
+		}
+		// clusterServersConfig.setPingTimeout(redissonProperties.getPingTimeout());
+		clusterServersConfig.setClientName(redissonProperties.getClientName());
+		clusterServersConfig.setConnectTimeout(redissonProperties.getConnectTimeout());
+		clusterServersConfig.setIdleConnectionTimeout(redissonProperties.getIdleConnectionTimeout());
+		clusterServersConfig.setKeepAlive(redissonProperties.getKeepAlive());
+		clusterServersConfig.setPassword(redissonProperties.getPassword());
+		clusterServersConfig.setPingConnectionInterval(redissonProperties.getPingConnectionInterval());
+		clusterServersConfig.setRetryAttempts(redissonProperties.getRetryAttempts());
+		clusterServersConfig.setRetryInterval(redissonProperties.getRetryInterval());
+		clusterServersConfig
+				.setSslEnableEndpointIdentification(redissonProperties.getSslEnableEndpointIdentification());
+		try {
+			if (null != redissonProperties.getSslKeystore()) {
+				clusterServersConfig.setSslKeystore(redissonProperties.getSslKeystore().toURL());
+			}
+			if (null != redissonProperties.getSslTruststore()) {
+				clusterServersConfig.setSslTruststore(redissonProperties.getSslTruststore().toURL());
+			}
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		clusterServersConfig.setSslKeystorePassword(redissonProperties.getSslKeystorePassword());
+		clusterServersConfig.setSslProvider(redissonProperties.getSslProvider());
+		clusterServersConfig.setSslTruststorePassword(redissonProperties.getSslTruststorePassword());
+		clusterServersConfig.setSubscriptionsPerConnection(redissonProperties.getSubscriptionsPerConnection());
+		clusterServersConfig.setTcpNoDelay(redissonProperties.getTcpNoDelay());
+		clusterServersConfig.setTimeout(redissonProperties.getTimeout());
+
+		return config;
+	}
+
+}

+ 110 - 0
apm-redis/src/main/java/com/persagy/common/redis/factory/MasterSlaveRedissionConfig.java

@@ -0,0 +1,110 @@
+package com.persagy.common.redis.factory;
+
+import com.persagy.common.redis.properties.MultipleServerConfig;
+import com.persagy.common.redis.properties.RedissonProperties;
+import org.redisson.Redisson;
+import org.redisson.api.RedissonClient;
+import org.redisson.client.codec.Codec;
+import org.redisson.config.Config;
+import org.redisson.config.MasterSlaveServersConfig;
+import org.redisson.connection.balancer.LoadBalancer;
+
+/**
+ * @version
+ * @description
+ * @company persagy
+ * @author zhangqiankun
+ * @since 2020年10月14日: 下午3:09:49
+ */
+public class MasterSlaveRedissionConfig {
+
+	public static RedissonClient redissonClient(RedissonProperties redissonProperties) {
+		return Redisson.create(initConfig(redissonProperties));
+	}
+
+	private static Config initConfig(RedissonProperties redissonProperties) {
+		Config config = new Config();
+		try {
+			config.setCodec((Codec) Class.forName(redissonProperties.getCodec().getCodecType()).newInstance());
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+		config.setTransportMode(redissonProperties.getTransportMode());
+		if (redissonProperties.getThreads() != null) {
+			config.setThreads(redissonProperties.getThreads());
+		}
+		if (redissonProperties.getNettyThreads() != null) {
+			config.setNettyThreads(redissonProperties.getNettyThreads());
+		}
+		config.setReferenceEnabled(redissonProperties.getReferenceEnabled());
+		config.setLockWatchdogTimeout(redissonProperties.getLockWatchdogTimeout());
+		config.setKeepPubSubOrder(redissonProperties.getKeepPubSubOrder());
+		config.setUseScriptCache(redissonProperties.getUseScriptCache());
+		config.setMinCleanUpDelay(redissonProperties.getMinCleanUpDelay());
+		config.setMaxCleanUpDelay(redissonProperties.getMaxCleanUpDelay());
+
+		MultipleServerConfig multipleServerConfig = redissonProperties.getMultipleServerConfig();
+
+		MasterSlaveServersConfig masterSlaveServersConfig = config.useMasterSlaveServers();
+		masterSlaveServersConfig.setDatabase(redissonProperties.getDatabase());
+		masterSlaveServersConfig
+				.setSlaveConnectionMinimumIdleSize(multipleServerConfig.getSlaveConnectionMinimumIdleSize());
+		masterSlaveServersConfig.setSlaveConnectionPoolSize(multipleServerConfig.getSlaveConnectionPoolSize());
+		masterSlaveServersConfig
+				.setFailedSlaveReconnectionInterval(multipleServerConfig.getFailedSlaveReconnectionInterval());
+		masterSlaveServersConfig.setFailedSlaveCheckInterval(multipleServerConfig.getFailedSlaveCheckInterval());
+		masterSlaveServersConfig
+				.setMasterConnectionMinimumIdleSize(multipleServerConfig.getMasterConnectionMinimumIdleSize());
+		masterSlaveServersConfig.setMasterConnectionPoolSize(multipleServerConfig.getMasterConnectionPoolSize());
+		masterSlaveServersConfig.setReadMode(multipleServerConfig.getReadMode());
+		masterSlaveServersConfig.setSubscriptionMode(multipleServerConfig.getSubscriptionMode());
+		masterSlaveServersConfig.setSubscriptionConnectionMinimumIdleSize(
+				multipleServerConfig.getSubscriptionConnectionMinimumIdleSize());
+		masterSlaveServersConfig
+				.setSubscriptionConnectionPoolSize(multipleServerConfig.getSubscriptionConnectionPoolSize());
+		masterSlaveServersConfig.setDnsMonitoringInterval(multipleServerConfig.getDnsMonitoringInterval());
+		try {
+			masterSlaveServersConfig.setLoadBalancer(
+					(LoadBalancer) Class.forName(multipleServerConfig.getLoadBalancer()).newInstance());
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+		int index = 0;
+		for (String nodeAddress : multipleServerConfig.getNodeAddresses()) {
+			if (index++ == 0) {
+				masterSlaveServersConfig.setMasterAddress(RedissonClientFactory.prefixAddress(nodeAddress));
+			} else {
+				masterSlaveServersConfig.addSlaveAddress(RedissonClientFactory.prefixAddress(nodeAddress));
+			}
+		}
+		masterSlaveServersConfig.setClientName(redissonProperties.getClientName());
+		masterSlaveServersConfig.setConnectTimeout(redissonProperties.getConnectTimeout());
+		masterSlaveServersConfig.setIdleConnectionTimeout(redissonProperties.getIdleConnectionTimeout());
+		masterSlaveServersConfig.setKeepAlive(redissonProperties.getKeepAlive());
+		masterSlaveServersConfig.setPassword(redissonProperties.getPassword());
+		masterSlaveServersConfig.setPingConnectionInterval(redissonProperties.getPingConnectionInterval());
+		masterSlaveServersConfig.setRetryAttempts(redissonProperties.getRetryAttempts());
+		masterSlaveServersConfig.setRetryInterval(redissonProperties.getRetryInterval());
+		masterSlaveServersConfig
+				.setSslEnableEndpointIdentification(redissonProperties.getSslEnableEndpointIdentification());
+		try {
+			if (null != redissonProperties.getSslKeystore()) {
+				masterSlaveServersConfig.setSslKeystore(redissonProperties.getSslKeystore().toURL());
+			}
+			if (null != redissonProperties.getSslTruststore()) {
+				masterSlaveServersConfig.setSslTruststore(redissonProperties.getSslTruststore().toURL());
+			}
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		masterSlaveServersConfig.setSslKeystorePassword(redissonProperties.getSslKeystorePassword());
+		masterSlaveServersConfig.setSslProvider(redissonProperties.getSslProvider());
+		masterSlaveServersConfig.setSslTruststorePassword(redissonProperties.getSslTruststorePassword());
+		masterSlaveServersConfig.setSubscriptionsPerConnection(redissonProperties.getSubscriptionsPerConnection());
+		masterSlaveServersConfig.setTcpNoDelay(redissonProperties.getTcpNoDelay());
+		masterSlaveServersConfig.setTimeout(redissonProperties.getTimeout());
+		
+		return config;
+	}
+
+}

+ 41 - 0
apm-redis/src/main/java/com/persagy/common/redis/factory/RedissonClientFactory.java

@@ -0,0 +1,41 @@
+package com.persagy.common.redis.factory;
+
+import com.persagy.common.redis.constant.RedisToolsConstant;
+import com.persagy.common.redis.properties.RedissonProperties;
+import com.persagy.common.utils.StringUtil;
+import org.redisson.api.RedissonClient;
+
+/**
+ * @version 
+ * @description 
+ * @company persagy
+ * @author zhangqiankun
+ * @since 2020年10月14日:	下午2:21:46
+ */
+public class RedissonClientFactory {
+	
+	public static RedissonClient redissonClient(RedissonProperties redissonProperties) {
+		switch (redissonProperties.getModel()) {
+			case SINGLE:
+				return SingleRedissionConfig.redissonClient(redissonProperties);
+			case SENTINEL:
+				return SentinelRedissionConfig.redissonClient(redissonProperties);
+			case MASTERSLAVE:
+				return MasterSlaveRedissionConfig.redissonClient(redissonProperties);
+			case CLUSTER:
+				return ClusterRedissionConfig.redissonClient(redissonProperties);
+			case REPLICATED:
+				return ReplicatedRedissionConfig.redissonClient(redissonProperties);
+			default:
+				return SingleRedissionConfig.redissonClient(redissonProperties);
+		}
+	}
+	
+	public static String prefixAddress(String address){
+		if (StringUtil.isBlank(address)) {
+			throw new NullPointerException("redis conection address is empty ...");
+		}
+        return RedisToolsConstant.REDIS_ADDRESS_PREFIX + address;
+    }
+    
+}

+ 106 - 0
apm-redis/src/main/java/com/persagy/common/redis/factory/ReplicatedRedissionConfig.java

@@ -0,0 +1,106 @@
+package com.persagy.common.redis.factory;
+
+import com.persagy.common.redis.properties.MultipleServerConfig;
+import com.persagy.common.redis.properties.RedissonProperties;
+import org.redisson.Redisson;
+import org.redisson.api.RedissonClient;
+import org.redisson.client.codec.Codec;
+import org.redisson.config.Config;
+import org.redisson.config.ReplicatedServersConfig;
+import org.redisson.connection.balancer.LoadBalancer;
+
+/**
+ * @version
+ * @description
+ * @company persagy
+ * @author zhangqiankun
+ * @since 2020年10月14日: 下午3:09:49
+ */
+public class ReplicatedRedissionConfig {
+
+	public static RedissonClient redissonClient(RedissonProperties redissonProperties) {
+		return Redisson.create(initConfig(redissonProperties));
+	}
+
+	private static Config initConfig(RedissonProperties redissonProperties) {
+		Config config = new Config();
+		try {
+			config.setCodec((Codec) Class.forName(redissonProperties.getCodec().getCodecType()).newInstance());
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+		config.setTransportMode(redissonProperties.getTransportMode());
+		if (redissonProperties.getThreads() != null) {
+			config.setThreads(redissonProperties.getThreads());
+		}
+		if (redissonProperties.getNettyThreads() != null) {
+			config.setNettyThreads(redissonProperties.getNettyThreads());
+		}
+		config.setReferenceEnabled(redissonProperties.getReferenceEnabled());
+		config.setLockWatchdogTimeout(redissonProperties.getLockWatchdogTimeout());
+		config.setKeepPubSubOrder(redissonProperties.getKeepPubSubOrder());
+		config.setUseScriptCache(redissonProperties.getUseScriptCache());
+		config.setMinCleanUpDelay(redissonProperties.getMinCleanUpDelay());
+		config.setMaxCleanUpDelay(redissonProperties.getMaxCleanUpDelay());
+
+		MultipleServerConfig multipleServerConfig = redissonProperties.getMultipleServerConfig();
+		
+		ReplicatedServersConfig replicatedServersConfig = config.useReplicatedServers();
+		replicatedServersConfig.setDatabase(redissonProperties.getDatabase());
+		replicatedServersConfig.setScanInterval(multipleServerConfig.getScanInterval());
+		replicatedServersConfig
+				.setSlaveConnectionMinimumIdleSize(multipleServerConfig.getSlaveConnectionMinimumIdleSize());
+		replicatedServersConfig.setSlaveConnectionPoolSize(multipleServerConfig.getSlaveConnectionPoolSize());
+		replicatedServersConfig
+				.setFailedSlaveReconnectionInterval(multipleServerConfig.getFailedSlaveReconnectionInterval());
+		replicatedServersConfig.setFailedSlaveCheckInterval(multipleServerConfig.getFailedSlaveCheckInterval());
+		replicatedServersConfig
+				.setMasterConnectionMinimumIdleSize(multipleServerConfig.getMasterConnectionMinimumIdleSize());
+		replicatedServersConfig.setMasterConnectionPoolSize(multipleServerConfig.getMasterConnectionPoolSize());
+		replicatedServersConfig.setReadMode(multipleServerConfig.getReadMode());
+		replicatedServersConfig.setSubscriptionMode(multipleServerConfig.getSubscriptionMode());
+		replicatedServersConfig.setSubscriptionConnectionMinimumIdleSize(
+				multipleServerConfig.getSubscriptionConnectionMinimumIdleSize());
+		replicatedServersConfig
+				.setSubscriptionConnectionPoolSize(multipleServerConfig.getSubscriptionConnectionPoolSize());
+		replicatedServersConfig.setDnsMonitoringInterval(multipleServerConfig.getDnsMonitoringInterval());
+		try {
+			replicatedServersConfig.setLoadBalancer(
+					(LoadBalancer) Class.forName(multipleServerConfig.getLoadBalancer()).newInstance());
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+		for (String nodeAddress : multipleServerConfig.getNodeAddresses()) {
+			replicatedServersConfig.addNodeAddress(RedissonClientFactory.prefixAddress(nodeAddress));
+		}
+		// replicatedServersConfig.setPingTimeout(redissonProperties.getPingTimeout());
+		replicatedServersConfig.setClientName(redissonProperties.getClientName());
+		replicatedServersConfig.setConnectTimeout(redissonProperties.getConnectTimeout());
+		replicatedServersConfig.setIdleConnectionTimeout(redissonProperties.getIdleConnectionTimeout());
+		replicatedServersConfig.setKeepAlive(redissonProperties.getKeepAlive());
+		replicatedServersConfig.setPassword(redissonProperties.getPassword());
+		replicatedServersConfig.setPingConnectionInterval(redissonProperties.getPingConnectionInterval());
+		replicatedServersConfig.setRetryAttempts(redissonProperties.getRetryAttempts());
+		replicatedServersConfig.setRetryInterval(redissonProperties.getRetryInterval());
+		replicatedServersConfig
+				.setSslEnableEndpointIdentification(redissonProperties.getSslEnableEndpointIdentification());
+		try {
+			if (null != redissonProperties.getSslKeystore()) {
+				replicatedServersConfig.setSslKeystore(redissonProperties.getSslKeystore().toURL());
+			}
+			if (null != redissonProperties.getSslTruststore()) {
+				replicatedServersConfig.setSslTruststore(redissonProperties.getSslTruststore().toURL());
+			}
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		replicatedServersConfig.setSslKeystorePassword(redissonProperties.getSslKeystorePassword());
+		replicatedServersConfig.setSslProvider(redissonProperties.getSslProvider());
+		replicatedServersConfig.setSslTruststorePassword(redissonProperties.getSslTruststorePassword());
+		replicatedServersConfig.setSubscriptionsPerConnection(redissonProperties.getSubscriptionsPerConnection());
+		replicatedServersConfig.setTcpNoDelay(redissonProperties.getTcpNoDelay());
+		replicatedServersConfig.setTimeout(redissonProperties.getTimeout());
+		return config;
+	}
+
+}

+ 108 - 0
apm-redis/src/main/java/com/persagy/common/redis/factory/SentinelRedissionConfig.java

@@ -0,0 +1,108 @@
+package com.persagy.common.redis.factory;
+
+import com.persagy.common.redis.properties.MultipleServerConfig;
+import com.persagy.common.redis.properties.RedissonProperties;
+import org.redisson.Redisson;
+import org.redisson.api.RedissonClient;
+import org.redisson.client.codec.Codec;
+import org.redisson.config.Config;
+import org.redisson.config.SentinelServersConfig;
+import org.redisson.connection.balancer.LoadBalancer;
+
+/**
+ * @version
+ * @description
+ * @company persagy
+ * @author zhangqiankun
+ * @since 2020年10月14日: 下午3:09:49
+ */
+public class SentinelRedissionConfig {
+
+	public static RedissonClient redissonClient(RedissonProperties redissonProperties) {
+		return Redisson.create(initConfig(redissonProperties));
+	}
+
+	private static Config initConfig(RedissonProperties redissonProperties) {
+		Config config = new Config();
+		try {
+			config.setCodec((Codec) Class.forName(redissonProperties.getCodec().getCodecType()).newInstance());
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+		config.setTransportMode(redissonProperties.getTransportMode());
+		if (redissonProperties.getThreads() != null) {
+			config.setThreads(redissonProperties.getThreads());
+		}
+		if (redissonProperties.getNettyThreads() != null) {
+			config.setNettyThreads(redissonProperties.getNettyThreads());
+		}
+		config.setReferenceEnabled(redissonProperties.getReferenceEnabled());
+		config.setLockWatchdogTimeout(redissonProperties.getLockWatchdogTimeout());
+		config.setKeepPubSubOrder(redissonProperties.getKeepPubSubOrder());
+		config.setUseScriptCache(redissonProperties.getUseScriptCache());
+		config.setMinCleanUpDelay(redissonProperties.getMinCleanUpDelay());
+		config.setMaxCleanUpDelay(redissonProperties.getMaxCleanUpDelay());
+
+		MultipleServerConfig multipleServerConfig = redissonProperties.getMultipleServerConfig();
+		
+		SentinelServersConfig sentinelServersConfig = config.useSentinelServers();
+		sentinelServersConfig.setDatabase(redissonProperties.getDatabase());
+		sentinelServersConfig.setMasterName(multipleServerConfig.getMasterName());
+		sentinelServersConfig.setScanInterval(multipleServerConfig.getScanInterval());
+		sentinelServersConfig
+				.setSlaveConnectionMinimumIdleSize(multipleServerConfig.getSlaveConnectionMinimumIdleSize());
+		sentinelServersConfig.setSlaveConnectionPoolSize(multipleServerConfig.getSlaveConnectionPoolSize());
+		sentinelServersConfig
+				.setFailedSlaveReconnectionInterval(multipleServerConfig.getFailedSlaveReconnectionInterval());
+		sentinelServersConfig.setFailedSlaveCheckInterval(multipleServerConfig.getFailedSlaveCheckInterval());
+		sentinelServersConfig
+				.setMasterConnectionMinimumIdleSize(multipleServerConfig.getMasterConnectionMinimumIdleSize());
+		sentinelServersConfig.setMasterConnectionPoolSize(multipleServerConfig.getMasterConnectionPoolSize());
+		sentinelServersConfig.setReadMode(multipleServerConfig.getReadMode());
+		sentinelServersConfig.setSubscriptionMode(multipleServerConfig.getSubscriptionMode());
+		sentinelServersConfig.setSubscriptionConnectionMinimumIdleSize(
+				multipleServerConfig.getSubscriptionConnectionMinimumIdleSize());
+		sentinelServersConfig
+				.setSubscriptionConnectionPoolSize(multipleServerConfig.getSubscriptionConnectionPoolSize());
+		sentinelServersConfig.setDnsMonitoringInterval(multipleServerConfig.getDnsMonitoringInterval());
+		try {
+			sentinelServersConfig.setLoadBalancer(
+					(LoadBalancer) Class.forName(multipleServerConfig.getLoadBalancer()).newInstance());
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+		for (String nodeAddress : multipleServerConfig.getNodeAddresses()) {
+			sentinelServersConfig.addSentinelAddress(RedissonClientFactory.prefixAddress(nodeAddress));
+		}
+		// sentinelServersConfig.setPingTimeout(redissonProperties.getPingTimeout());
+		sentinelServersConfig.setClientName(redissonProperties.getClientName());
+		sentinelServersConfig.setConnectTimeout(redissonProperties.getConnectTimeout());
+		sentinelServersConfig.setIdleConnectionTimeout(redissonProperties.getIdleConnectionTimeout());
+		sentinelServersConfig.setKeepAlive(redissonProperties.getKeepAlive());
+		sentinelServersConfig.setPassword(redissonProperties.getPassword());
+		sentinelServersConfig.setPingConnectionInterval(redissonProperties.getPingConnectionInterval());
+		sentinelServersConfig.setRetryAttempts(redissonProperties.getRetryAttempts());
+		sentinelServersConfig.setRetryInterval(redissonProperties.getRetryInterval());
+		sentinelServersConfig
+				.setSslEnableEndpointIdentification(redissonProperties.getSslEnableEndpointIdentification());
+		try {
+			if (null != redissonProperties.getSslKeystore()) {
+				sentinelServersConfig.setSslKeystore(redissonProperties.getSslKeystore().toURL());
+			}
+			if (null != redissonProperties.getSslTruststore()) {
+				sentinelServersConfig.setSslTruststore(redissonProperties.getSslTruststore().toURL());
+			}
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		sentinelServersConfig.setSslKeystorePassword(redissonProperties.getSslKeystorePassword());
+		sentinelServersConfig.setSslProvider(redissonProperties.getSslProvider());
+		sentinelServersConfig.setSslTruststorePassword(redissonProperties.getSslTruststorePassword());
+		sentinelServersConfig.setSubscriptionsPerConnection(redissonProperties.getSubscriptionsPerConnection());
+		sentinelServersConfig.setTcpNoDelay(redissonProperties.getTcpNoDelay());
+		sentinelServersConfig.setTimeout(redissonProperties.getTimeout());
+
+		return config;
+	}
+
+}

+ 88 - 0
apm-redis/src/main/java/com/persagy/common/redis/factory/SingleRedissionConfig.java

@@ -0,0 +1,88 @@
+package com.persagy.common.redis.factory;
+
+import com.persagy.common.redis.properties.RedissonProperties;
+import org.redisson.Redisson;
+import org.redisson.api.RedissonClient;
+import org.redisson.client.codec.Codec;
+import org.redisson.config.Config;
+import org.redisson.config.SingleServerConfig;
+
+/**
+ * @version 
+ * @description 
+ * @company persagy
+ * @author zhangqiankun
+ * @since 2020年10月14日:	下午3:09:49
+ */
+public class SingleRedissionConfig {
+	
+	/**
+	 * 
+	 * @param redissonProperties
+	 * @return
+	 */
+	public static RedissonClient redissonClient(RedissonProperties redissonProperties){
+        return Redisson.create(initConfig(redissonProperties));
+    }
+	
+	private static Config initConfig(RedissonProperties redissonProperties) {
+		Config config = new Config();
+		try {
+			config.setCodec((Codec) Class.forName(redissonProperties.getCodec().getCodecType()).newInstance());
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+		config.setTransportMode(redissonProperties.getTransportMode());
+		if (redissonProperties.getThreads() != null) {
+			config.setThreads(redissonProperties.getThreads());
+		}
+		if (redissonProperties.getNettyThreads() != null) {
+			config.setNettyThreads(redissonProperties.getNettyThreads());
+		}
+		config.setReferenceEnabled(redissonProperties.getReferenceEnabled());
+		config.setLockWatchdogTimeout(redissonProperties.getLockWatchdogTimeout());
+		config.setKeepPubSubOrder(redissonProperties.getKeepPubSubOrder());
+		config.setUseScriptCache(redissonProperties.getUseScriptCache());
+		config.setMinCleanUpDelay(redissonProperties.getMinCleanUpDelay());
+		config.setMaxCleanUpDelay(redissonProperties.getMaxCleanUpDelay());
+		
+		SingleServerConfig singleServerConfig = config.useSingleServer();
+        com.persagy.common.redis.properties.SingleServerConfig param = redissonProperties.getSingleServerConfig();
+        singleServerConfig.setAddress(RedissonClientFactory.prefixAddress(param.getAddress()));
+        singleServerConfig.setConnectionMinimumIdleSize(param.getConnectionMinimumIdleSize());
+        singleServerConfig.setConnectionPoolSize(param.getConnectionPoolSize());
+        singleServerConfig.setDatabase(redissonProperties.getDatabase());
+        singleServerConfig.setDnsMonitoringInterval(param.getDnsMonitoringInterval());
+        singleServerConfig.setSubscriptionConnectionMinimumIdleSize(param.getSubscriptionConnectionMinimumIdleSize());
+        singleServerConfig.setSubscriptionConnectionPoolSize(param.getSubscriptionConnectionPoolSize());
+        // singleServerConfig.setPingTimeout(redissonProperties.getPingTimeout());
+        singleServerConfig.setClientName(redissonProperties.getClientName());
+        singleServerConfig.setConnectTimeout(redissonProperties.getConnectTimeout());
+        singleServerConfig.setIdleConnectionTimeout(redissonProperties.getIdleConnectionTimeout());
+        singleServerConfig.setKeepAlive(redissonProperties.getKeepAlive());
+        singleServerConfig.setPassword(redissonProperties.getPassword());
+        singleServerConfig.setPingConnectionInterval(redissonProperties.getPingConnectionInterval());
+        singleServerConfig.setRetryAttempts(redissonProperties.getRetryAttempts());
+        singleServerConfig.setRetryInterval(redissonProperties.getRetryInterval());
+        singleServerConfig.setSslEnableEndpointIdentification(redissonProperties.getSslEnableEndpointIdentification());
+        try{
+            if (null!=redissonProperties.getSslKeystore()){
+                singleServerConfig.setSslKeystore(redissonProperties.getSslKeystore().toURL());
+            }
+            if (null!=redissonProperties.getSslTruststore()){
+                singleServerConfig.setSslTruststore(redissonProperties.getSslTruststore().toURL());
+            }
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+        singleServerConfig.setSslKeystorePassword(redissonProperties.getSslKeystorePassword());
+        singleServerConfig.setSslProvider(redissonProperties.getSslProvider());
+        singleServerConfig.setSslTruststorePassword(redissonProperties.getSslTruststorePassword());
+        singleServerConfig.setSubscriptionsPerConnection(redissonProperties.getSubscriptionsPerConnection());
+        singleServerConfig.setTcpNoDelay(redissonProperties.getTcpNoDelay());
+        singleServerConfig.setTimeout(redissonProperties.getTimeout());
+        
+        return config;
+	}
+	
+}

+ 43 - 0
apm-redis/src/main/java/com/persagy/common/redis/model/CodecModel.java

@@ -0,0 +1,43 @@
+package com.persagy.common.redis.model;
+
+public enum CodecModel {
+    /**Jackson JSON 编码 默认编码*/
+    JSON_JACKSON_CODEC("org.redisson.codec.JsonJacksonCodec"),
+    /**Avro 一个二进制的JSON编码*/
+    AVRO_JACKSON_CODEC("org.redisson.codec.AvroJacksonCodec"),
+    /**Smile 另一个二进制的JSON编码*/
+    SMILE_JACKSON_CODEC("org.redisson.codec.SmileJacksonCodec"),
+    /**CBOR又一个二进制的JSON编码*/
+    CBOR_JACKSON_CODEC("org.redisson.codec.CborJacksonCodec"),
+    /**MsgPack 再来一个二进制的JSON编码*/
+    MSG_PACK_JACKSON_CODEC("org.redisson.codec.MsgPackJacksonCodec"),
+    /**Amazon Ion 亚马逊的Ion编码,格式与JSON类似*/
+    ION_JACKSON_CODEC("org.redisson.codec.IonJacksonCodec"),
+    /**Kryo 二进制对象序列化编码*/
+    KRYO_CODEC("org.redisson.codec.KryoCodec"),
+    /**JDK序列化编码*/
+    SERIALIZATION_CODEC("org.redisson.codec.SerializationCodec"),
+    /**FST 10倍于JDK序列化性能而且100%兼容的编码*/
+    FST_CODEC("org.redisson.codec.FstCodec"),
+    /**LZ4 压缩型序列化对象编码*/
+    LZ4_CODEC("org.redisson.codec.LZ4Codec"),
+    /**Snappy 另一个压缩型序列化对象编码*/
+    SNAPPY_CODEC("org.redisson.codec.SnappyCodec"),
+    /**基于Jackson的映射类使用的编码。可用于避免序列化类的信息,以及用于解决使用byte[]遇到的问题。*/
+    JSON_JACKSON_MAP_CODEC("org.redisson.client.codec.JsonJacksonMapCodec"),
+    /**纯字符串编码(无转换)*/
+    STRING_CODEC("org.redisson.client.codec.StringCodec"),
+    /**纯整长型数字编码(无转换)*/
+    LONG_CODEC("org.redisson.client.codec.LongCodec"),
+    /**字节数组编码*/
+    BYTE_ARRAY_CODEC("org.redisson.client.codec.ByteArrayCodec"),
+    /**用来组合多种不同编码在一起*/
+    COMPOSITE_CODEC("org.redisson.codec.CompositeCodec");
+
+    private String codecType;
+    CodecModel(String codecType){this.codecType=codecType;}
+
+    public String getCodecType() {
+        return codecType;
+    }
+}

+ 14 - 0
apm-redis/src/main/java/com/persagy/common/redis/model/Model.java

@@ -0,0 +1,14 @@
+package com.persagy.common.redis.model;
+
+public enum Model {
+    //哨兵
+    SENTINEL,
+    //主从
+    MASTERSLAVE,
+    //单例
+    SINGLE,
+    //集群
+    CLUSTER,
+    //云托管模式
+    REPLICATED
+}

+ 40 - 0
apm-redis/src/main/java/com/persagy/common/redis/model/SerializerModel.java

@@ -0,0 +1,40 @@
+package com.persagy.common.redis.model;
+
+import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer;
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
+import org.springframework.data.redis.serializer.RedisSerializer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+public enum  SerializerModel {
+    /**StringRedisSerializer,字符串序列化器.key必须是字符串*/
+    GENERIC_TO_STRING_SERIALIZER(new StringRedisSerializer()),
+    
+    /**FastJsonRedisSerializer,fastJson的序列化器*/
+    FAST_JSON_REDIS_SERIALIZER(new FastJsonRedisSerializer<Object>(Object.class)),
+    
+    /**Jackson2JsonRedisSerializer,Jackson2Json的序列化器*/
+    JACKSON_TO_JSON_REDIS_SERIALIZER(new Jackson2JsonRedisSerializer<Object>(Object.class)),
+    
+    /**redis默认的jdk序列化器,严重浪费redis内存的一款*/
+    CBOR_JACKSON_CODEC(new JdkSerializationRedisSerializer());
+
+    private RedisSerializer<Object> serializerType;
+    
+    SerializerModel(RedisSerializer serializerType) {
+    	this.serializerType = serializerType;
+    }
+
+    public RedisSerializer<Object> getSerializerType() {
+    	if (serializerType instanceof Jackson2JsonRedisSerializer) {
+    		ObjectMapper objectMapper = new ObjectMapper();
+            objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
+            objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
+    		((Jackson2JsonRedisSerializer<Object>) serializerType).setObjectMapper(objectMapper);
+		}
+        return serializerType;
+    }
+}

+ 31 - 0
apm-redis/src/main/java/com/persagy/common/redis/properties/CacheManagerProperties.java

@@ -0,0 +1,31 @@
+package com.persagy.common.redis.properties;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+import java.util.List;
+
+/**
+ * @author zlt
+ * @date 2019/1/6
+ */
+@Setter
+@Getter
+@ConfigurationProperties(prefix = "integrated.cache-manager")
+public class CacheManagerProperties {
+    private List<CacheConfig> configs;
+
+    @Setter
+    @Getter
+    public static class CacheConfig {
+        /**
+         * cache key
+         */
+        private String key;
+        /**
+         * 过期时间,sec
+         */
+        private long second = 60;
+    }
+}

+ 155 - 0
apm-redis/src/main/java/com/persagy/common/redis/properties/MultipleServerConfig.java

@@ -0,0 +1,155 @@
+package com.persagy.common.redis.properties;
+
+import org.redisson.config.ReadMode;
+import org.redisson.config.SubscriptionMode;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 多节点配置
+ */
+public class MultipleServerConfig {
+
+    private String loadBalancer = "org.redisson.connection.balancer.RoundRobinLoadBalancer";
+    private Integer slaveConnectionMinimumIdleSize = 32;
+    private Integer slaveConnectionPoolSize = 64;
+    private Integer failedSlaveReconnectionInterval = 3000;
+    private Integer failedSlaveCheckInterval = 180000;
+    private Integer masterConnectionMinimumIdleSize = 32;
+    private Integer masterConnectionPoolSize = 64;
+    private ReadMode readMode= ReadMode.SLAVE;
+    private SubscriptionMode subscriptionMode= SubscriptionMode.SLAVE;
+    private Integer subscriptionConnectionMinimumIdleSize=1;
+    private Integer subscriptionConnectionPoolSize=50;
+    private Long dnsMonitoringInterval=5000L;
+
+    private List<String> nodeAddresses = new ArrayList<String>();
+
+    //集群,哨兵,云托管
+    private Integer scanInterval = 1000;
+
+    //哨兵模式
+    private String masterName;
+
+    public String getMasterName() {
+        return masterName;
+    }
+
+    public void setMasterName(String masterName) {
+        this.masterName = masterName;
+    }
+
+    public String getLoadBalancer() {
+        return loadBalancer;
+    }
+
+    public void setLoadBalancer(String loadBalancer) {
+        this.loadBalancer = loadBalancer;
+    }
+
+    public Integer getSlaveConnectionMinimumIdleSize() {
+        return slaveConnectionMinimumIdleSize;
+    }
+
+    public Integer getSlaveConnectionPoolSize() {
+        return slaveConnectionPoolSize;
+    }
+
+    public Integer getFailedSlaveReconnectionInterval() {
+        return failedSlaveReconnectionInterval;
+    }
+
+    public Integer getFailedSlaveCheckInterval() {
+        return failedSlaveCheckInterval;
+    }
+
+    public Integer getMasterConnectionMinimumIdleSize() {
+        return masterConnectionMinimumIdleSize;
+    }
+
+    public Integer getMasterConnectionPoolSize() {
+        return masterConnectionPoolSize;
+    }
+
+    public ReadMode getReadMode() {
+        return readMode;
+    }
+
+    public SubscriptionMode getSubscriptionMode() {
+        return subscriptionMode;
+    }
+
+    public Integer getSubscriptionConnectionMinimumIdleSize() {
+        return subscriptionConnectionMinimumIdleSize;
+    }
+
+    public Integer getSubscriptionConnectionPoolSize() {
+        return subscriptionConnectionPoolSize;
+    }
+
+    public Long getDnsMonitoringInterval() {
+        return dnsMonitoringInterval;
+    }
+
+    public List<String> getNodeAddresses() {
+        return nodeAddresses;
+    }
+
+    public void setNodeAddresses(List<String> nodeAddresses) {
+        this.nodeAddresses = nodeAddresses;
+    }
+
+    public Integer getScanInterval() {
+        return scanInterval;
+    }
+
+    public void setScanInterval(Integer scanInterval) {
+        this.scanInterval = scanInterval;
+    }
+
+
+    public void setSlaveConnectionMinimumIdleSize(Integer slaveConnectionMinimumIdleSize) {
+        this.slaveConnectionMinimumIdleSize = slaveConnectionMinimumIdleSize;
+    }
+
+    public void setSlaveConnectionPoolSize(Integer slaveConnectionPoolSize) {
+        this.slaveConnectionPoolSize = slaveConnectionPoolSize;
+    }
+
+    public void setFailedSlaveReconnectionInterval(Integer failedSlaveReconnectionInterval) {
+        this.failedSlaveReconnectionInterval = failedSlaveReconnectionInterval;
+    }
+
+    public void setFailedSlaveCheckInterval(Integer failedSlaveCheckInterval) {
+        this.failedSlaveCheckInterval = failedSlaveCheckInterval;
+    }
+
+    public void setMasterConnectionMinimumIdleSize(Integer masterConnectionMinimumIdleSize) {
+        this.masterConnectionMinimumIdleSize = masterConnectionMinimumIdleSize;
+    }
+
+    public void setMasterConnectionPoolSize(Integer masterConnectionPoolSize) {
+        this.masterConnectionPoolSize = masterConnectionPoolSize;
+    }
+
+    public void setReadMode(ReadMode readMode) {
+        this.readMode = readMode;
+    }
+
+    public void setSubscriptionMode(SubscriptionMode subscriptionMode) {
+        this.subscriptionMode = subscriptionMode;
+    }
+
+    public void setSubscriptionConnectionMinimumIdleSize(Integer subscriptionConnectionMinimumIdleSize) {
+        this.subscriptionConnectionMinimumIdleSize = subscriptionConnectionMinimumIdleSize;
+    }
+
+    public void setSubscriptionConnectionPoolSize(Integer subscriptionConnectionPoolSize) {
+        this.subscriptionConnectionPoolSize = subscriptionConnectionPoolSize;
+    }
+
+    public void setDnsMonitoringInterval(Long dnsMonitoringInterval) {
+        this.dnsMonitoringInterval = dnsMonitoringInterval;
+    }
+}

+ 419 - 0
apm-redis/src/main/java/com/persagy/common/redis/properties/RedissonProperties.java

@@ -0,0 +1,419 @@
+package com.persagy.common.redis.properties;
+
+
+import com.persagy.common.model.LockModel;
+import com.persagy.common.redis.model.CodecModel;
+import com.persagy.common.redis.model.Model;
+import com.persagy.common.redis.model.SerializerModel;
+import org.redisson.config.SslProvider;
+import org.redisson.config.TransportMode;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.context.properties.NestedConfigurationProperty;
+
+import java.net.URI;
+
+@ConfigurationProperties(prefix = "integrated.redisson")
+public class RedissonProperties {
+
+    private Model model= Model.SINGLE;
+    private CodecModel codec= CodecModel.JSON_JACKSON_CODEC;
+    private SerializerModel serializerModel= SerializerModel.JACKSON_TO_JSON_REDIS_SERIALIZER;
+    private Integer threads;
+    private Integer nettyThreads;
+    private TransportMode transportMode= TransportMode.NIO;
+
+    //公共参数
+    private int database = 0;
+    private String password;
+    private Integer idleConnectionTimeout = 10000;
+    private Integer pingTimeout = 1000;
+    private Integer connectTimeout = 10000;
+    private Integer timeout = 3000;
+    private Integer retryAttempts = 3;
+    private Integer retryInterval = 1500;
+    private Integer subscriptionsPerConnection = 5;
+    private String clientName;
+    private Boolean sslEnableEndpointIdentification = true;
+    private SslProvider sslProvider= SslProvider.JDK;
+    private URI sslTruststore;
+    private String sslTruststorePassword;
+    private URI sslKeystore;
+    private String sslKeystorePassword;
+    private Integer pingConnectionInterval=0;
+    private Boolean keepAlive=false;
+    private Boolean tcpNoDelay=false;
+    private Boolean referenceEnabled = true;
+    private Long lockWatchdogTimeout=30000L;
+    private Boolean keepPubSubOrder=true;
+    private Boolean decodeInExecutor=false;
+    private Boolean useScriptCache=false;
+    private Integer minCleanUpDelay=5;
+    private Integer maxCleanUpDelay=1800;
+    //锁的模式 如果不设置 单个key默认可重入锁 多个key默认联锁
+    private LockModel lockModel;
+
+    //等待加锁超时时间 -1一直等待
+    private Long attemptTimeout= 10000L;
+
+    //数据缓存时间 默认30分钟
+    private Long dataValidTime=1000*60* 30L;
+    //结束
+
+    @NestedConfigurationProperty
+    private SingleServerConfig singleServerConfig;
+    
+    @NestedConfigurationProperty
+    private MultipleServerConfig multipleServerConfig;
+
+    public SerializerModel getSerializerModel() {
+        return serializerModel;
+    }
+
+    public void setSerializerModel(SerializerModel serializerModel) {
+        this.serializerModel = serializerModel;
+    }
+
+    public int getDatabase() {
+		return database;
+	}
+
+	public void setDatabase(int database) {
+		this.database = database;
+	}
+
+	public Long getDataValidTime() {
+        return dataValidTime;
+    }
+
+    public void setDataValidTime(Long dataValidTime) {
+        this.dataValidTime = dataValidTime;
+    }
+
+    public LockModel getLockModel() {
+        return lockModel;
+    }
+
+    public void setLockModel(LockModel lockModel) {
+        this.lockModel = lockModel;
+    }
+
+    public Long getAttemptTimeout() {
+        return attemptTimeout;
+    }
+
+    public void setAttemptTimeout(Long attemptTimeout) {
+        this.attemptTimeout = attemptTimeout;
+    }
+
+    public Boolean getReferenceEnabled() {
+        return referenceEnabled;
+    }
+
+    public void setReferenceEnabled(Boolean referenceEnabled) {
+        this.referenceEnabled = referenceEnabled;
+    }
+
+    public Long getLockWatchdogTimeout() {
+        return lockWatchdogTimeout;
+    }
+
+    public void setLockWatchdogTimeout(Long lockWatchdogTimeout) {
+        this.lockWatchdogTimeout = lockWatchdogTimeout;
+    }
+
+    public Boolean getKeepPubSubOrder() {
+        return keepPubSubOrder;
+    }
+
+    public void setKeepPubSubOrder(Boolean keepPubSubOrder) {
+        this.keepPubSubOrder = keepPubSubOrder;
+    }
+
+    public Boolean getDecodeInExecutor() {
+        return decodeInExecutor;
+    }
+
+    public void setDecodeInExecutor(Boolean decodeInExecutor) {
+        this.decodeInExecutor = decodeInExecutor;
+    }
+
+    public Boolean getUseScriptCache() {
+        return useScriptCache;
+    }
+
+    public void setUseScriptCache(Boolean useScriptCache) {
+        this.useScriptCache = useScriptCache;
+    }
+
+    public Integer getMinCleanUpDelay() {
+        return minCleanUpDelay;
+    }
+
+    public void setMinCleanUpDelay(Integer minCleanUpDelay) {
+        this.minCleanUpDelay = minCleanUpDelay;
+    }
+
+    public Integer getMaxCleanUpDelay() {
+        return maxCleanUpDelay;
+    }
+
+    public void setMaxCleanUpDelay(Integer maxCleanUpDelay) {
+        this.maxCleanUpDelay = maxCleanUpDelay;
+    }
+
+    public Model getModel() {
+        return model;
+    }
+
+    public void setModel(Model model) {
+        this.model = model;
+    }
+
+    public SingleServerConfig getSingleServerConfig() {
+        return singleServerConfig;
+    }
+
+    public void setSingleServerConfig(SingleServerConfig singleServerConfig) {
+        this.singleServerConfig = singleServerConfig;
+    }
+
+    public MultipleServerConfig getMultipleServerConfig() {
+        return multipleServerConfig;
+    }
+
+    public void setMultipleServerConfig(MultipleServerConfig multipleServerConfig) {
+        this.multipleServerConfig = multipleServerConfig;
+    }
+
+    public void setIdleConnectionTimeout(Integer idleConnectionTimeout) {
+        this.idleConnectionTimeout = idleConnectionTimeout;
+    }
+
+    public void setPingTimeout(Integer pingTimeout) {
+        this.pingTimeout = pingTimeout;
+    }
+
+    public void setConnectTimeout(Integer connectTimeout) {
+        this.connectTimeout = connectTimeout;
+    }
+
+    public void setTimeout(Integer timeout) {
+        this.timeout = timeout;
+    }
+
+    public void setRetryAttempts(Integer retryAttempts) {
+        this.retryAttempts = retryAttempts;
+    }
+
+    public void setRetryInterval(Integer retryInterval) {
+        this.retryInterval = retryInterval;
+    }
+
+    public void setSubscriptionsPerConnection(Integer subscriptionsPerConnection) {
+        this.subscriptionsPerConnection = subscriptionsPerConnection;
+    }
+
+    public Boolean getSslEnableEndpointIdentification() {
+        return sslEnableEndpointIdentification;
+    }
+
+    public void setSslEnableEndpointIdentification(Boolean sslEnableEndpointIdentification) {
+        this.sslEnableEndpointIdentification = sslEnableEndpointIdentification;
+    }
+
+    public void setPingConnectionInterval(Integer pingConnectionInterval) {
+        this.pingConnectionInterval = pingConnectionInterval;
+    }
+
+    public Boolean getKeepAlive() {
+        return keepAlive;
+    }
+
+    public void setKeepAlive(Boolean keepAlive) {
+        this.keepAlive = keepAlive;
+    }
+
+    public Boolean getTcpNoDelay() {
+        return tcpNoDelay;
+    }
+
+    public void setTcpNoDelay(Boolean tcpNoDelay) {
+        this.tcpNoDelay = tcpNoDelay;
+    }
+
+    public Integer getThreads() {
+        return threads;
+    }
+
+    public void setThreads(Integer threads) {
+        this.threads = threads;
+    }
+
+    public Integer getNettyThreads() {
+        return nettyThreads;
+    }
+
+    public void setNettyThreads(Integer nettyThreads) {
+        this.nettyThreads = nettyThreads;
+    }
+
+    public TransportMode getTransportMode() {
+        return transportMode;
+    }
+
+    public void setTransportMode(TransportMode transportMode) {
+        this.transportMode = transportMode;
+    }
+
+    public CodecModel getCodec() {
+        return codec;
+    }
+
+    public void setCodec(CodecModel codec) {
+        this.codec = codec;
+    }
+
+    public int getIdleConnectionTimeout() {
+        return idleConnectionTimeout;
+    }
+
+    public void setIdleConnectionTimeout(int idleConnectionTimeout) {
+        this.idleConnectionTimeout = idleConnectionTimeout;
+    }
+
+    public int getPingTimeout() {
+        return pingTimeout;
+    }
+
+    public void setPingTimeout(int pingTimeout) {
+        this.pingTimeout = pingTimeout;
+    }
+
+    public int getConnectTimeout() {
+        return connectTimeout;
+    }
+
+    public void setConnectTimeout(int connectTimeout) {
+        this.connectTimeout = connectTimeout;
+    }
+
+    public int getTimeout() {
+        return timeout;
+    }
+
+    public void setTimeout(int timeout) {
+        this.timeout = timeout;
+    }
+
+    public int getRetryAttempts() {
+        return retryAttempts;
+    }
+
+    public void setRetryAttempts(int retryAttempts) {
+        this.retryAttempts = retryAttempts;
+    }
+
+    public int getRetryInterval() {
+        return retryInterval;
+    }
+
+    public void setRetryInterval(int retryInterval) {
+        this.retryInterval = retryInterval;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public int getSubscriptionsPerConnection() {
+        return subscriptionsPerConnection;
+    }
+
+    public void setSubscriptionsPerConnection(int subscriptionsPerConnection) {
+        this.subscriptionsPerConnection = subscriptionsPerConnection;
+    }
+
+    public String getClientName() {
+        return clientName;
+    }
+
+    public void setClientName(String clientName) {
+        this.clientName = clientName;
+    }
+
+    public boolean isSslEnableEndpointIdentification() {
+        return sslEnableEndpointIdentification;
+    }
+
+    public void setSslEnableEndpointIdentification(boolean sslEnableEndpointIdentification) {
+        this.sslEnableEndpointIdentification = sslEnableEndpointIdentification;
+    }
+
+    public SslProvider getSslProvider() {
+        return sslProvider;
+    }
+
+    public void setSslProvider(SslProvider sslProvider) {
+        this.sslProvider = sslProvider;
+    }
+
+    public URI getSslTruststore() {
+        return sslTruststore;
+    }
+
+    public void setSslTruststore(URI sslTruststore) {
+        this.sslTruststore = sslTruststore;
+    }
+
+    public String getSslTruststorePassword() {
+        return sslTruststorePassword;
+    }
+
+    public void setSslTruststorePassword(String sslTruststorePassword) {
+        this.sslTruststorePassword = sslTruststorePassword;
+    }
+
+    public URI getSslKeystore() {
+        return sslKeystore;
+    }
+
+    public void setSslKeystore(URI sslKeystore) {
+        this.sslKeystore = sslKeystore;
+    }
+
+    public String getSslKeystorePassword() {
+        return sslKeystorePassword;
+    }
+
+    public void setSslKeystorePassword(String sslKeystorePassword) {
+        this.sslKeystorePassword = sslKeystorePassword;
+    }
+
+    public int getPingConnectionInterval() {
+        return pingConnectionInterval;
+    }
+
+    public void setPingConnectionInterval(int pingConnectionInterval) {
+        this.pingConnectionInterval = pingConnectionInterval;
+    }
+
+    public boolean isKeepAlive() {
+        return keepAlive;
+    }
+
+    public void setKeepAlive(boolean keepAlive) {
+        this.keepAlive = keepAlive;
+    }
+
+    public boolean isTcpNoDelay() {
+        return tcpNoDelay;
+    }
+
+    public void setTcpNoDelay(boolean tcpNoDelay) {
+        this.tcpNoDelay = tcpNoDelay;
+    }
+}

+ 65 - 0
apm-redis/src/main/java/com/persagy/common/redis/properties/SingleServerConfig.java

@@ -0,0 +1,65 @@
+package com.persagy.common.redis.properties;
+
+
+/**
+ * 单节点配置
+ */
+public class SingleServerConfig {
+	
+	private static final String DEFAULT_ADDRESS = "127.0.0.1:6379";
+	
+    private String address;
+    private Integer subscriptionConnectionMinimumIdleSize = 1;
+    private Integer subscriptionConnectionPoolSize = 50;
+    private Integer connectionMinimumIdleSize = 32;
+    private Integer connectionPoolSize = 64;
+    private Long dnsMonitoringInterval = 5000L;
+
+    public String getAddress() {
+        return address == null ? DEFAULT_ADDRESS : address;
+    }
+
+    public void setAddress(String address) {
+        this.address = address;
+    }
+
+    public Integer getSubscriptionConnectionMinimumIdleSize() {
+        return subscriptionConnectionMinimumIdleSize;
+    }
+
+    public void setSubscriptionConnectionMinimumIdleSize(Integer subscriptionConnectionMinimumIdleSize) {
+        this.subscriptionConnectionMinimumIdleSize = subscriptionConnectionMinimumIdleSize;
+    }
+
+    public Integer getSubscriptionConnectionPoolSize() {
+        return subscriptionConnectionPoolSize;
+    }
+
+    public void setSubscriptionConnectionPoolSize(Integer subscriptionConnectionPoolSize) {
+        this.subscriptionConnectionPoolSize = subscriptionConnectionPoolSize;
+    }
+
+    public Integer getConnectionMinimumIdleSize() {
+        return connectionMinimumIdleSize;
+    }
+
+    public void setConnectionMinimumIdleSize(Integer connectionMinimumIdleSize) {
+        this.connectionMinimumIdleSize = connectionMinimumIdleSize;
+    }
+
+    public Integer getConnectionPoolSize() {
+        return connectionPoolSize;
+    }
+
+    public void setConnectionPoolSize(Integer connectionPoolSize) {
+        this.connectionPoolSize = connectionPoolSize;
+    }
+
+    public Long getDnsMonitoringInterval() {
+        return dnsMonitoringInterval;
+    }
+
+    public void setDnsMonitoringInterval(Long dnsMonitoringInterval) {
+        this.dnsMonitoringInterval = dnsMonitoringInterval;
+    }
+}

+ 493 - 0
apm-redis/src/main/java/com/persagy/common/redis/template/RedissonTemplateImpl.java

@@ -0,0 +1,493 @@
+package com.persagy.common.redis.template;
+
+import com.alibaba.fastjson.JSONObject;
+import com.persagy.common.constant.CommonConstant;
+import com.persagy.common.exception.LockException;
+import com.persagy.common.redis.base.RedissonTemplate;
+import com.persagy.common.redis.boot.RedisBeanContext;
+import org.redisson.api.RLock;
+import org.redisson.api.RedissonClient;
+import org.springframework.data.redis.connection.RedisStringCommands;
+import org.springframework.data.redis.core.*;
+import org.springframework.data.redis.core.script.RedisScript;
+import org.springframework.data.redis.core.types.Expiration;
+import org.springframework.util.StringUtils;
+
+import java.nio.charset.Charset;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+
+public class RedissonTemplateImpl implements RedissonTemplate {
+    /**默认的数据库索引-0*/
+    private static final Integer DEFAULT_DATABASE_INDEX = 0;
+    
+    /**默认的上锁成功标志-1L*/
+    private static final Long RELEASE_SUCCESS = 1L;
+
+    private final int database;
+    
+    public RedissonTemplateImpl(Integer database) {
+    	this.database = database == null || database < 0 ? DEFAULT_DATABASE_INDEX : database;
+    }
+    
+    @Override
+    public Boolean exists(Integer databaseIndex, String key) {
+        Boolean hasKey = RedisBeanContext.getRedisTemplate(databaseIndex).hasKey(key);
+        if (null!=hasKey && hasKey){
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public Boolean exists(String key) {
+        return exists(database, key);
+    }
+
+    @Override
+    public Long length(Integer databaseIndex, String key) {
+        return RedisBeanContext.getRedisTemplate(databaseIndex).boundValueOps(key).size();
+    }
+
+    @Override
+    public Long length(String key) {
+        return length(database, key);
+    }
+
+    @Override
+    public void setObj(String key, Object obj) {
+        setObj(database, key, obj);
+    }
+
+    @Override
+    public void setObj(Integer databaseIndex, String key, Object obj) {
+        RedisBeanContext.getRedisTemplate(databaseIndex).boundValueOps(key).set(JSONObject.toJSONString(obj));
+    }
+
+    @Override
+    public void set(String key, String value) {
+        set(database, key, value);
+    }
+
+    @Override
+    public void set(Integer databaseIndex, String key, String value) {
+        RedisTemplate<Object, Object> redisTemplate = RedisBeanContext.getRedisTemplate(databaseIndex);
+        redisTemplate.boundValueOps(key).set(value);
+    }
+
+    @Override
+    public void setex(String key, String value, int seconds) {
+        setex(database, key, value, seconds);
+    }
+
+    @Override
+    public void setex(Integer databaseIndex, String key, String value, int seconds) {
+        if (seconds<0){
+            set(databaseIndex, key, value);
+            return;
+        }
+        RedisBeanContext.getRedisTemplate(databaseIndex).boundValueOps(key).set(value,seconds, TimeUnit.SECONDS);
+    }
+
+    @Override
+    public void setexObj(Integer databaseIndex, String key, Object obj, int seconds) {
+        if (seconds<0){
+            setObj(databaseIndex, key, obj);
+            return;
+        }
+        RedisBeanContext.getRedisTemplate(databaseIndex).boundValueOps(key).set(JSONObject.toJSONString(obj),seconds, TimeUnit.SECONDS);
+    }
+
+    @Override
+    public String get(String key) {
+        return get(database, key);
+    }
+
+    @Override
+    public String get(Integer databaseIndex, String key) {
+        RedisTemplate<String, String> redisTemplate = RedisBeanContext.getRedisTemplate(databaseIndex);
+        return redisTemplate.boundValueOps(key).get();
+    }
+
+    @Override
+    public List<String> get(String... keys) {
+        return get(database, keys);
+    }
+
+    @Override
+    public List<String> get(Integer databaseIndex, String... keys) {
+        RedisTemplate<String, String> redisTemplate = RedisBeanContext.getRedisTemplate(databaseIndex);
+        return redisTemplate.opsForValue().multiGet(Arrays.asList(keys));
+    }
+
+    @Override
+    public Set<String> scan(int databaseIndex, String regx) {
+        RedisTemplate<String, String> redisTemplate = RedisBeanContext.getRedisTemplate(databaseIndex);
+        return redisTemplate.execute((RedisCallback<Set<String>>) connection -> {
+            Set<String> keysTmp = new HashSet<>();
+            Cursor<byte[]> cursor = connection.scan(new ScanOptions.ScanOptionsBuilder().match(regx).count(Long.MAX_VALUE).build());
+            while (cursor.hasNext()) {
+                keysTmp.add(new String(cursor.next()));
+            }
+            return keysTmp;
+        });
+    }
+
+    @Override
+    public Set<String> scan(String regx) {
+        return scan(database, regx);
+    }
+
+    @Override
+    public <T> T getObj(String key, Class<T> clazz) {
+        return getObj(database, key, clazz);
+    }
+
+    @Override
+    public <T> T getObj(Integer databaseIndex, String key, Class<T> clazz) {
+        RedisTemplate<String, String> redisTemplate = RedisBeanContext.getRedisTemplate(databaseIndex);
+        BoundValueOperations<String, String> operations = redisTemplate.boundValueOps(key);
+        String objStr = operations.get();
+        if (StringUtils.isEmpty(objStr)){
+            return null;
+        }
+        return JSONObject.parseObject(objStr, clazz);
+    }
+
+    @Override
+    public Long getTtl(Integer databaseIndex, String key) {
+        RedisTemplate<String, String> redisTemplate = RedisBeanContext.getRedisTemplate(databaseIndex);
+        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
+    }
+
+    @Override
+    public Long getTtl(String key) {
+        return getTtl(database, key);
+    }
+
+    @Override
+    public void setTtl(Integer databaseIndex, String key, int seconds) {
+        RedisTemplate<String, String> redisTemplate = RedisBeanContext.getRedisTemplate(databaseIndex);
+        redisTemplate.expire(key,seconds, TimeUnit.SECONDS);
+    }
+
+    @Override
+    public void setTtl(String key, int seconds) {
+        setTtl(database, key, seconds);
+    }
+
+    @Override
+    public Boolean removeTtl(Integer databaseIndex, String key) {
+        RedisTemplate<String, String> redisTemplate = RedisBeanContext.getRedisTemplate(databaseIndex);
+        return redisTemplate.expire(key,-1L,TimeUnit.SECONDS);
+    }
+
+    @Override
+    public Boolean removeTtl(String key) {
+        return removeTtl(database,key);
+    }
+
+    @Override
+    public Boolean delete(String key) {
+        return delete(database, key);
+    }
+
+    @Override
+    public Boolean delete(Integer databaseIndex, String key) {
+        RedisTemplate<String, String> redisTemplate = RedisBeanContext.getRedisTemplate(databaseIndex);
+        return redisTemplate.delete(key);
+    }
+
+    @Override
+    public Long incr(Integer databaseIndex, String key) {
+        RedisTemplate<String, String> redisTemplate = RedisBeanContext.getRedisTemplate(databaseIndex);
+        return redisTemplate.opsForValue().increment(key,1);
+    }
+
+    @Override
+    public Long incr(String key) {
+        return incr(database,key);
+    }
+
+    @Override
+    public void hset(Integer databaseIndex, String key, String field, String value) {
+        RedisTemplate<String, String> redisTemplate = RedisBeanContext.getRedisTemplate(databaseIndex);
+        BoundHashOperations<String, String, String> hashOperations = redisTemplate.boundHashOps(key);
+        hashOperations.put(field,value);
+    }
+
+    @Override
+    public void hset(String key, String field, String value) {
+        hset(database, key, field, value);
+    }
+
+    @Override
+    public String hget(Integer databaseIndex, String key, String field) {
+        RedisTemplate<String, String> redisTemplate = RedisBeanContext.getRedisTemplate(databaseIndex);
+        BoundHashOperations<String, String, String> hashOperations = redisTemplate.boundHashOps(key);
+        return hashOperations.get(field);
+    }
+
+    @Override
+    public String hget(String key, String field) {
+        return hget(database, key, field);
+    }
+
+    @Override
+    public Long hdel(Integer databaseIndex, String key, String field) {
+        RedisTemplate<String, String> redisTemplate = RedisBeanContext.getRedisTemplate(databaseIndex);
+        BoundHashOperations<String, String, String> hashOperations = redisTemplate.boundHashOps(key);
+        return hashOperations.delete(field);
+    }
+
+    @Override
+    public Long hdel(String key, String field) {
+        return hdel(database, key, field);
+    }
+
+    @Override
+    public void hmset(Integer databaseIndex, String key, Map<String, String> map) {
+        RedisTemplate<String, String> redisTemplate = RedisBeanContext.getRedisTemplate(databaseIndex);
+        BoundHashOperations<String, String, String> hashOperations = redisTemplate.boundHashOps(key);
+        hashOperations.putAll(map);
+    }
+
+    @Override
+    public void hmset(String key, Map<String, String> map) {
+        hmset(database, key, map);
+    }
+
+    @Override
+    public List<String> hmget(Integer databaseIndex, String key, String... fields) {
+        RedisTemplate<String, String> redisTemplate = RedisBeanContext.getRedisTemplate(databaseIndex);
+        BoundHashOperations<String, String, String> hashOperations = redisTemplate.boundHashOps(key);
+        return hashOperations.multiGet(Arrays.asList(fields));
+    }
+
+    @Override
+    public List<String> hmget(String key, String... fields) {
+        return hmget(database, key, fields);
+    }
+
+    @Override
+    public Long hlen(Integer databaseIndex, String key) {
+        RedisTemplate<String, String> redisTemplate = RedisBeanContext.getRedisTemplate(databaseIndex);
+        BoundHashOperations<String, String, String> hashOperations = redisTemplate.boundHashOps(key);
+        return hashOperations.size();
+    }
+
+    @Override
+    public Long hlen(String key) {
+        return hlen(database, key);
+    }
+
+    @Override
+    public Map<String, String> hgetAll(Integer databaseIndex, String key) {
+        RedisTemplate<String, String> redisTemplate = RedisBeanContext.getRedisTemplate(databaseIndex);
+        BoundHashOperations<String, String, String> hashOperations = redisTemplate.boundHashOps(key);
+        return hashOperations.entries();
+    }
+
+    @Override
+    public Map<String, String> hgetAll(String key) {
+        return hgetAll(database, key);
+    }
+
+    @Override
+    public void lpush(Integer databaseIndex, String key, String... values) {
+        RedisTemplate<String, String> redisTemplate = RedisBeanContext.getRedisTemplate(databaseIndex);
+        BoundListOperations<String, String> listOperations = redisTemplate.boundListOps(key);
+        listOperations.leftPushAll(values);
+    }
+
+    @Override
+    public void lpush(String key, String... values) {
+        lpush(database, key, values);
+    }
+
+    @Override
+    public void rpush(Integer databaseIndex, String key, String... values) {
+        RedisTemplate<String, String> redisTemplate = RedisBeanContext.getRedisTemplate(databaseIndex);
+        BoundListOperations<String, String> listOperations = redisTemplate.boundListOps(key);
+        listOperations.rightPushAll(values);
+    }
+
+    @Override
+    public void rpush(String key, String... values) {
+        rpush(database, key, values);
+    }
+
+    @Override
+    public Long llen(Integer databaseIndex, String key) {
+        RedisTemplate<String, String> redisTemplate = RedisBeanContext.getRedisTemplate(databaseIndex);
+        BoundListOperations<String, String> listOperations = redisTemplate.boundListOps(key);
+        return listOperations.size();
+    }
+
+    @Override
+    public Long llen(String key) {
+        return llen(database, key);
+    }
+
+    @Override
+    public String lindex(Integer databaseIndex, String key, long index) {
+        RedisTemplate<String, String> redisTemplate = RedisBeanContext.getRedisTemplate(databaseIndex);
+        BoundListOperations<String, String> listOperations = redisTemplate.boundListOps(key);
+        return listOperations.index(index);
+    }
+
+    @Override
+    public String lindex(String key, long index) {
+        return lindex(database, key, index);
+    }
+
+    @Override
+    public List<String> lrangeAll(Integer databaseIndex, String key) {
+        RedisTemplate<String, String> redisTemplate = RedisBeanContext.getRedisTemplate(databaseIndex);
+        BoundListOperations<String, String> listOperations = redisTemplate.boundListOps(key);
+        return listOperations.range(0, -1);
+    }
+
+    @Override
+    public List<String> lrangeAll(String key) {
+        return lrangeAll(database, key);
+    }
+
+    @Override
+    public List<String> lrange(Integer databaseIndex, String key, long start, long end) {
+        RedisTemplate<String, String> redisTemplate = RedisBeanContext.getRedisTemplate(databaseIndex);
+        BoundListOperations<String, String> listOperations = redisTemplate.boundListOps(key);
+        return listOperations.range(start, end);
+    }
+
+    @Override
+    public List<String> lrange(String key, long start, long end) {
+        return lrange(database, key, start, end);
+    }
+
+    @Override
+    public String lpop(Integer databaseIndex, String key) {
+        RedisTemplate<String, String> redisTemplate = RedisBeanContext.getRedisTemplate(databaseIndex);
+        BoundListOperations<String, String> listOperations = redisTemplate.boundListOps(key);
+        return listOperations.leftPop();
+    }
+
+    @Override
+    public String lpop(String key) {
+        return lpop(database, key);
+    }
+
+    @Override
+    public String rpop(Integer databaseIndex, String key) {
+        RedisTemplate<String, String> redisTemplate = RedisBeanContext.getRedisTemplate(databaseIndex);
+        BoundListOperations<String, String> listOperations = redisTemplate.boundListOps(key);
+        return listOperations.rightPop();
+    }
+
+    @Override
+    public String rpop(String key) {
+        return rpop(database, key);
+    }
+
+    @Override
+    public Boolean tryLock(Integer databaseIndex, String lockKey, String lockValue, long expire) {
+        RedisTemplate<String, String> redisTemplate = RedisBeanContext.getRedisTemplate(databaseIndex);
+        Boolean result = redisTemplate.execute((RedisCallback<Boolean>) connection -> {
+            byte[] key = lockKey.getBytes(Charset.forName("UTF-8"));
+            byte[] value = lockValue.getBytes(Charset.forName("UTF-8"));
+            Expiration expiration = Expiration.seconds(TimeUnit.SECONDS.toSeconds(expire));
+            RedisStringCommands.SetOption option = RedisStringCommands.SetOption.SET_IF_ABSENT;
+            return connection.set(key, value, expiration, option);
+        });
+
+        if (null!=result && result) {
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public Boolean tryLock(String lockKey, String lockValue, long expire) {
+        return tryLock(database, lockKey, lockValue, expire);
+    }
+
+    @Override
+    public Boolean unLock(Integer databaseIndex, String lockKey, String lockValue) {
+        RedisTemplate<String, String> redisTemplate = RedisBeanContext.getRedisTemplate(databaseIndex);
+        if (StringUtils.isEmpty(lockValue)) {
+            String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
+            Object execute = redisTemplate.execute(RedisScript.of(script,Long.class), Collections.singletonList(lockKey), lockValue);
+            if (RELEASE_SUCCESS.equals(execute)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public Boolean unLock(String lockKey, String lockValue) {
+        return unLock(database, lockKey, lockValue);
+    }
+
+    private RLock getLock(String key, boolean isFair) {
+        RedissonClient redisson = RedisBeanContext.getRedissonClient(database);
+        if (isFair) {
+            return redisson.getFairLock(CommonConstant.LOCK_KEY_PREFIX + key);
+        }
+        return redisson.getLock(CommonConstant.LOCK_KEY_PREFIX + key);
+    }
+
+    @Override
+    public RLock lock(String key, long leaseTime, TimeUnit unit, boolean isFair) {
+        RLock lock = getLock(key, isFair);
+        lock.lock(leaseTime, unit);
+        return lock;
+    }
+    @Override
+    public RLock lock(String key, long leaseTime, TimeUnit unit) {
+        return lock(key, leaseTime, unit, false);
+    }
+    @Override
+    public RLock lock(String key, boolean isFair) {
+        return lock(key, -1, null, isFair);
+    }
+    @Override
+    public RLock lock(String key) {
+        return lock(key, -1, null, false);
+    }
+
+    @Override
+    public RLock tryLock(String key, long waitTime, long leaseTime, TimeUnit unit, boolean isFair) throws InterruptedException {
+        RLock lock = getLock(key, isFair);
+        if (lock.tryLock(waitTime, leaseTime, unit)) {
+            return lock;
+        }
+        return null;
+    }
+    @Override
+    public RLock tryLock(String key, long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException {
+        return tryLock(key, waitTime, leaseTime, unit, false);
+    }
+    @Override
+    public RLock tryLock(String key, long waitTime, TimeUnit unit, boolean isFair) throws InterruptedException {
+        return tryLock(key, waitTime, -1, unit, isFair);
+    }
+    @Override
+    public RLock tryLock(String key, long waitTime, TimeUnit unit) throws InterruptedException {
+        return tryLock(key, waitTime, -1, unit, false);
+    }
+
+    @Override
+    public void unlock(Object lock) {
+        if (lock != null) {
+            if (lock instanceof RLock) {
+                RLock rLock = (RLock)lock;
+                if (rLock.isLocked()) {
+                    rLock.unlock();
+                }
+            } else {
+                throw new LockException("requires RLock type");
+            }
+        }
+    }
+}

+ 37 - 0
apm-redis/src/main/java/com/persagy/common/utils/StringUtil.java

@@ -0,0 +1,37 @@
+package com.persagy.common.utils;
+
+import cn.hutool.core.util.StrUtil;
+
+/**
+ * @version 
+ * @description 
+ * @company persagy
+ * @author zhangqiankun
+ * @since 2020年8月26日:	下午5:22:35
+ */
+public class StringUtil extends StrUtil {
+	
+	/**
+	 * 判断两个字符串是否都为空,或都不为空
+	 * @return true-全空、全不为空;否则-false
+	 */
+	public static boolean concurIsNullOrExists(String param1, String param2) {
+		if (isBlank(param1) && isBlank(param2)) {
+			return true;
+		} 
+		if (isNotBlank(param1) && isNotBlank(param2)) {
+			return true;
+		}
+		return false;
+	}
+	
+	
+	/**
+	 * 移除字符串中指定的前缀和后缀
+	 */
+	public static String removePreAndSuffix(String param, String prefix, String suffix) {
+		param = StringUtil.removePrefix(param, prefix);
+		return StringUtil.removeSuffix(param, suffix);
+	}
+	
+}

+ 1 - 0
pom.xml

@@ -20,5 +20,6 @@
         <module>apm-translate</module>
         <module>apm-mybatis</module>
         <module>apm-package</module>
+        <module>apm-redis</module>
     </modules>
 </project>