Преглед изворни кода

update 升级 luttuce 为 redisson 性能更强 工具更全

疯狂的狮子li пре 3 година
родитељ
комит
99c4692a0d

+ 8 - 0
pom.xml

@@ -31,6 +31,7 @@
         <feign.version>2.2.6.RELEASE</feign.version>
         <feign-okhttp.version>11.0</feign-okhttp.version>
         <spring-boot-admin.version>2.3.1</spring-boot-admin.version>
+        <redisson.version>3.15.2</redisson.version>
     </properties>
 
     <!-- 依赖声明 -->
@@ -180,6 +181,13 @@
                 <version>${ruoyi-vue-plus.version}</version>
             </dependency>
 
+            <!--redisson-->
+            <dependency>
+                <groupId>org.redisson</groupId>
+                <artifactId>redisson-spring-boot-starter</artifactId>
+                <version>${redisson.version}</version>
+            </dependency>
+
         </dependencies>
     </dependencyManagement>
 

+ 35 - 10
ruoyi-admin/src/main/resources/application-dev.yml

@@ -67,13 +67,38 @@ spring:
     password:
     # 连接超时时间
     timeout: 10s
-    lettuce:
-      pool:
-        # 连接池中的最小空闲连接
-        min-idle: 0
-        # 连接池中的最大空闲连接
-        max-idle: 8
-        # 连接池的最大数据库连接数
-        max-active: 8
-        # #连接池最大阻塞等待时间(使用负值表示没有限制)
-        max-wait: -1ms
+    # 是否开启ssl
+    ssl: false
+
+--- # redisson 客户端配置
+redisson:
+  # 线程池数量
+  threads: 16
+  # Netty线程池数量
+  nettyThreads: 32
+  # 传输模式
+  transportMode: "NIO"
+  # 单节点配置
+  singleServerConfig:
+    # 客户端名称
+    clientName: ${ruoyi-vue-plus.name}
+    # 最小空闲连接数
+    connectionMinimumIdleSize: 32
+    # 连接池大小
+    connectionPoolSize: 64
+    # 连接空闲超时,单位:毫秒
+    idleConnectionTimeout: 10000
+    # 命令等待超时,单位:毫秒
+    timeout: 3000
+    # 如果尝试在此限制之内发送成功,则开始启用 timeout 计时。
+    retryAttempts: 3
+    # 命令重试发送时间间隔,单位:毫秒
+    retryInterval: 1500
+    # 发布和订阅连接的最小空闲连接数
+    subscriptionConnectionMinimumIdleSize: 1
+    # 发布和订阅连接池大小
+    subscriptionConnectionPoolSize: 50
+    # 单个连接最大订阅数量
+    subscriptionsPerConnection: 5
+    # DNS监测时间间隔,单位:毫秒
+    dnsMonitoringInterval: 5000

+ 35 - 10
ruoyi-admin/src/main/resources/application-prod.yml

@@ -67,13 +67,38 @@ spring:
     password:
     # 连接超时时间
     timeout: 10s
-    lettuce:
-      pool:
-        # 连接池中的最小空闲连接
-        min-idle: 0
-        # 连接池中的最大空闲连接
-        max-idle: 8
-        # 连接池的最大数据库连接数
-        max-active: 8
-        # #连接池最大阻塞等待时间(使用负值表示没有限制)
-        max-wait: -1ms
+    # 是否开启ssl
+    ssl: false
+
+--- # redisson 客户端配置
+redisson:
+  # 线程池数量
+  threads: 16
+  # Netty线程池数量
+  nettyThreads: 32
+  # 传输模式
+  transportMode: "NIO"
+  # 单节点配置
+  singleServerConfig:
+    # 客户端名称
+    clientName: ${ruoyi-vue-plus.name}
+    # 最小空闲连接数
+    connectionMinimumIdleSize: 32
+    # 连接池大小
+    connectionPoolSize: 64
+    # 连接空闲超时,单位:毫秒
+    idleConnectionTimeout: 10000
+    # 命令等待超时,单位:毫秒
+    timeout: 3000
+    # 如果尝试在此限制之内发送成功,则开始启用 timeout 计时。
+    retryAttempts: 3
+    # 命令重试发送时间间隔,单位:毫秒
+    retryInterval: 1500
+    # 发布和订阅连接的最小空闲连接数
+    subscriptionConnectionMinimumIdleSize: 1
+    # 发布和订阅连接池大小
+    subscriptionConnectionPoolSize: 50
+    # 单个连接最大订阅数量
+    subscriptionsPerConnection: 5
+    # DNS监测时间间隔,单位:毫秒
+    dnsMonitoringInterval: 5000

+ 6 - 0
ruoyi-common/pom.xml

@@ -151,6 +151,12 @@
             <artifactId>spring-boot-configuration-processor</artifactId>
         </dependency>
 
+        <!--redisson-->
+        <dependency>
+            <groupId>org.redisson</groupId>
+            <artifactId>redisson-spring-boot-starter</artifactId>
+        </dependency>
+
     </dependencies>
 
 </project>

+ 208 - 223
ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java

@@ -1,234 +1,219 @@
 package com.ruoyi.common.core.redis;
 
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
+import com.google.common.collect.Lists;
+import org.redisson.api.*;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.redis.core.BoundSetOperations;
-import org.springframework.data.redis.core.HashOperations;
-import org.springframework.data.redis.core.RedisTemplate;
-import org.springframework.data.redis.core.ValueOperations;
 import org.springframework.stereotype.Component;
 
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+
 /**
  * spring redis 工具类
  *
- * @author ruoyi
+ * @author shenxinquan
  **/
-@SuppressWarnings(value = { "unchecked", "rawtypes" })
+@SuppressWarnings(value = {"unchecked", "rawtypes"})
 @Component
-public class RedisCache
-{
-    @Autowired
-    public RedisTemplate redisTemplate;
-
-    /**
-     * 缓存基本的对象,Integer、String、实体类等
-     *
-     * @param key 缓存的键值
-     * @param value 缓存的值
-     */
-    public <T> void setCacheObject(final String key, final T value)
-    {
-        redisTemplate.opsForValue().set(key, value);
-    }
-
-    /**
-     * 缓存基本的对象,Integer、String、实体类等
-     *
-     * @param key 缓存的键值
-     * @param value 缓存的值
-     * @param timeout 时间
-     * @param timeUnit 时间颗粒度
-     */
-    public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit)
-    {
-        redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
-    }
-
-    /**
-     * 设置有效时间
-     *
-     * @param key Redis键
-     * @param timeout 超时时间
-     * @return true=设置成功;false=设置失败
-     */
-    public boolean expire(final String key, final long timeout)
-    {
-        return expire(key, timeout, TimeUnit.SECONDS);
-    }
-
-    /**
-     * 设置有效时间
-     *
-     * @param key Redis键
-     * @param timeout 超时时间
-     * @param unit 时间单位
-     * @return true=设置成功;false=设置失败
-     */
-    public boolean expire(final String key, final long timeout, final TimeUnit unit)
-    {
-        return redisTemplate.expire(key, timeout, unit);
-    }
-
-    /**
-     * 获得缓存的基本对象。
-     *
-     * @param key 缓存键值
-     * @return 缓存键值对应的数据
-     */
-    public <T> T getCacheObject(final String key)
-    {
-        ValueOperations<String, T> operation = redisTemplate.opsForValue();
-        return operation.get(key);
-    }
-
-    /**
-     * 删除单个对象
-     *
-     * @param key
-     */
-    public boolean deleteObject(final String key)
-    {
-        return redisTemplate.delete(key);
-    }
-
-    /**
-     * 删除集合对象
-     *
-     * @param collection 多个对象
-     * @return
-     */
-    public long deleteObject(final Collection collection)
-    {
-        return redisTemplate.delete(collection);
-    }
-
-    /**
-     * 缓存List数据
-     *
-     * @param key 缓存的键值
-     * @param dataList 待缓存的List数据
-     * @return 缓存的对象
-     */
-    public <T> long setCacheList(final String key, final List<T> dataList)
-    {
-        Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
-        return count == null ? 0 : count;
-    }
-
-    /**
-     * 获得缓存的list对象
-     *
-     * @param key 缓存的键值
-     * @return 缓存键值对应的数据
-     */
-    public <T> List<T> getCacheList(final String key)
-    {
-        return redisTemplate.opsForList().range(key, 0, -1);
-    }
-
-    /**
-     * 缓存Set
-     *
-     * @param key 缓存键值
-     * @param dataSet 缓存的数据
-     * @return 缓存数据的对象
-     */
-    public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet)
-    {
-        BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
-        Iterator<T> it = dataSet.iterator();
-        while (it.hasNext())
-        {
-            setOperation.add(it.next());
-        }
-        return setOperation;
-    }
-
-    /**
-     * 获得缓存的set
-     *
-     * @param key
-     * @return
-     */
-    public <T> Set<T> getCacheSet(final String key)
-    {
-        return redisTemplate.opsForSet().members(key);
-    }
-
-    /**
-     * 缓存Map
-     *
-     * @param key
-     * @param dataMap
-     */
-    public <T> void setCacheMap(final String key, final Map<String, T> dataMap)
-    {
-        if (dataMap != null) {
-            redisTemplate.opsForHash().putAll(key, dataMap);
-        }
-    }
-
-    /**
-     * 获得缓存的Map
-     *
-     * @param key
-     * @return
-     */
-    public <T> Map<String, T> getCacheMap(final String key)
-    {
-        return redisTemplate.opsForHash().entries(key);
-    }
-
-    /**
-     * 往Hash中存入数据
-     *
-     * @param key Redis键
-     * @param hKey Hash键
-     * @param value 值
-     */
-    public <T> void setCacheMapValue(final String key, final String hKey, final T value)
-    {
-        redisTemplate.opsForHash().put(key, hKey, value);
-    }
-
-    /**
-     * 获取Hash中的数据
-     *
-     * @param key Redis键
-     * @param hKey Hash键
-     * @return Hash中的对象
-     */
-    public <T> T getCacheMapValue(final String key, final String hKey)
-    {
-        HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
-        return opsForHash.get(key, hKey);
-    }
-
-    /**
-     * 获取多个Hash中的数据
-     *
-     * @param key Redis键
-     * @param hKeys Hash键集合
-     * @return Hash对象集合
-     */
-    public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys)
-    {
-        return redisTemplate.opsForHash().multiGet(key, hKeys);
-    }
-
-    /**
-     * 获得缓存的基本对象列表
-     *
-     * @param pattern 字符串前缀
-     * @return 对象列表
-     */
-    public Collection<String> keys(final String pattern)
-    {
-        return redisTemplate.keys(pattern);
-    }
+public class RedisCache {
+
+	@Autowired
+	private RedissonClient redissonClient;
+
+	/**
+	 * 缓存基本的对象,Integer、String、实体类等
+	 *
+	 * @param key   缓存的键值
+	 * @param value 缓存的值
+	 */
+	public <T> void setCacheObject(final String key, final T value) {
+		redissonClient.getBucket(key).set(value);
+	}
+
+	/**
+	 * 缓存基本的对象,Integer、String、实体类等
+	 *
+	 * @param key      缓存的键值
+	 * @param value    缓存的值
+	 * @param timeout  时间
+	 * @param timeUnit 时间颗粒度
+	 */
+	public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) {
+		RBucket<T> result = redissonClient.getBucket(key);
+		result.set(value);
+		result.expire(timeout, timeUnit);
+	}
+
+	/**
+	 * 设置有效时间
+	 *
+	 * @param key     Redis键
+	 * @param timeout 超时时间
+	 * @return true=设置成功;false=设置失败
+	 */
+	public boolean expire(final String key, final long timeout) {
+		return expire(key, timeout, TimeUnit.SECONDS);
+	}
+
+	/**
+	 * 设置有效时间
+	 *
+	 * @param key     Redis键
+	 * @param timeout 超时时间
+	 * @param unit    时间单位
+	 * @return true=设置成功;false=设置失败
+	 */
+	public boolean expire(final String key, final long timeout, final TimeUnit unit) {
+		RBucket rBucket = redissonClient.getBucket(key);
+		return rBucket.expire(timeout, unit);
+	}
+
+	/**
+	 * 获得缓存的基本对象。
+	 *
+	 * @param key 缓存键值
+	 * @return 缓存键值对应的数据
+	 */
+	public <T> T getCacheObject(final String key) {
+		RBucket<T> rBucket = redissonClient.getBucket(key);
+		return rBucket.get();
+	}
+
+	/**
+	 * 删除单个对象
+	 *
+	 * @param key
+	 */
+	public boolean deleteObject(final String key) {
+		return redissonClient.getBucket(key).delete();
+	}
+
+	/* */
+
+	/**
+	 * 删除集合对象
+	 *
+	 * @param collection 多个对象
+	 * @return
+	 */
+	public long deleteObject(final Collection collection) {
+		return redissonClient.getKeys().delete(Arrays.toString(collection.toArray()));
+	}
+
+	/**
+	 * 缓存List数据
+	 *
+	 * @param key      缓存的键值
+	 * @param dataList 待缓存的List数据
+	 * @return 缓存的对象
+	 */
+	public <T> boolean setCacheList(final String key, final List<T> dataList) {
+		RList<T> rList = redissonClient.getList(key);
+		return rList.addAll(dataList);
+	}
+
+	/**
+	 * 获得缓存的list对象
+	 *
+	 * @param key 缓存的键值
+	 * @return 缓存键值对应的数据
+	 */
+	public <T> List<T> getCacheList(final String key) {
+		RList<T> rList = redissonClient.getList(key);
+		return rList.readAll();
+	}
+
+	/**
+	 * 缓存Set
+	 *
+	 * @param key     缓存键值
+	 * @param dataSet 缓存的数据
+	 * @return 缓存数据的对象
+	 */
+	public <T> boolean setCacheSet(final String key, final Set<T> dataSet) {
+		RSet<T> rSet = redissonClient.getSet(key);
+		return rSet.addAll(dataSet);
+	}
+
+	/**
+	 * 获得缓存的set
+	 *
+	 * @param key
+	 * @return
+	 */
+	public <T> Set<T> getCacheSet(final String key) {
+		RSet<T> rSet = redissonClient.getSet(key);
+		return rSet.readAll();
+	}
+
+	/**
+	 * 缓存Map
+	 *
+	 * @param key
+	 * @param dataMap
+	 */
+	public <T> void setCacheMap(final String key, final Map<String, T> dataMap) {
+		if (dataMap != null) {
+			RMap<String, T> rMap = redissonClient.getMap(key);
+			rMap.putAll(dataMap);
+		}
+	}
+
+	/**
+	 * 获得缓存的Map
+	 *
+	 * @param key
+	 * @return
+	 */
+	public <T> Map<String, T> getCacheMap(final String key) {
+		RMap<String, T> rMap = redissonClient.getMap(key);
+		return rMap.getAll(rMap.keySet());
+	}
+
+	/**
+	 * 往Hash中存入数据
+	 *
+	 * @param key   Redis键
+	 * @param hKey  Hash键
+	 * @param value 值
+	 */
+	public <T> void setCacheMapValue(final String key, final String hKey, final T value) {
+		RMap<String, T> rMap = redissonClient.getMap(key);
+		rMap.put(hKey, value);
+	}
+
+	/**
+	 * 获取Hash中的数据
+	 *
+	 * @param key  Redis键
+	 * @param hKey Hash键
+	 * @return Hash中的对象
+	 */
+	public <T> T getCacheMapValue(final String key, final String hKey) {
+		RMap<String, T> rMap = redissonClient.getMap(key);
+		return rMap.get(hKey);
+	}
+
+	/**
+	 * 获取多个Hash中的数据
+	 *
+	 * @param key   Redis键
+	 * @param hKeys Hash键集合
+	 * @return Hash对象集合
+	 */
+	public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys) {
+		RListMultimap rListMultimap = redissonClient.getListMultimap(key);
+		return rListMultimap.getAll(hKeys);
+	}
+
+	/**
+	 * 获得缓存的基本对象列表
+	 *
+	 * @param pattern 字符串前缀
+	 * @return 对象列表
+	 */
+	public Collection<String> keys(final String pattern) {
+		Iterable<String> iterable = redissonClient.getKeys().getKeysByPattern(pattern);
+		return Lists.newArrayList(iterable);
+	}
 }

+ 55 - 28
ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java

@@ -1,42 +1,69 @@
 package com.ruoyi.framework.config;
 
-import com.alibaba.fastjson.support.spring.GenericFastJsonRedisSerializer;
+import com.ruoyi.framework.config.properties.RedissonProperties;
+import org.redisson.Redisson;
+import org.redisson.api.RedissonClient;
+import org.redisson.codec.JsonJacksonCodec;
+import org.redisson.config.Config;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
 import org.springframework.cache.annotation.CachingConfigurerSupport;
 import org.springframework.cache.annotation.EnableCaching;
 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.serializer.StringRedisSerializer;
+
+import java.io.IOException;
 
 /**
  * redis配置
  *
- * @author ruoyi
+ * @author Lion Li
  */
 @Configuration
 @EnableCaching
-public class RedisConfig extends CachingConfigurerSupport
-{
-    @Bean
-    @SuppressWarnings(value = { "unchecked", "rawtypes" })
-    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory)
-    {
-        RedisTemplate<Object, Object> template = new RedisTemplate<>();
-        template.setConnectionFactory(connectionFactory);
-
-        GenericFastJsonRedisSerializer serializer = new GenericFastJsonRedisSerializer();
-		StringRedisSerializer keySerializer = new StringRedisSerializer();
-
-        // 使用StringRedisSerializer来序列化和反序列化redis的key值
-		template.setKeySerializer(keySerializer);
-        template.setValueSerializer(serializer);
-
-        // Hash的key也采用StringRedisSerializer的序列化方式
-        template.setHashKeySerializer(keySerializer);
-        template.setHashValueSerializer(serializer);
-
-        template.afterPropertiesSet();
-        return template;
-    }
+public class RedisConfig extends CachingConfigurerSupport {
+
+	private static final String REDIS_PROTOCOL_PREFIX = "redis://";
+	private static final String REDISS_PROTOCOL_PREFIX = "rediss://";
+
+	@Autowired
+	private RedisProperties redisProperties;
+
+	@Autowired
+	private RedissonProperties redissonProperties;
+
+	@Bean(destroyMethod = "shutdown")
+	@ConditionalOnMissingBean(RedissonClient.class)
+	public RedissonClient redisson() throws IOException {
+		String prefix = REDIS_PROTOCOL_PREFIX;
+		if (redisProperties.isSsl()) {
+			prefix = REDISS_PROTOCOL_PREFIX;
+		}
+		Config config = new Config();
+		config.setThreads(redissonProperties.getThreads())
+			.setNettyThreads(redissonProperties.getNettyThreads())
+			.setCodec(JsonJacksonCodec.INSTANCE)
+			.setTransportMode(redissonProperties.getTransportMode());
+
+		RedissonProperties.SingleServerConfig singleServerConfig = redissonProperties.getSingleServerConfig();
+		// 使用单机模式
+		config.useSingleServer()
+			.setAddress(prefix + redisProperties.getHost() + ":" + redisProperties.getPort())
+			.setConnectTimeout(((Long) redisProperties.getTimeout().toMillis()).intValue())
+			.setDatabase(redisProperties.getDatabase())
+			.setPassword(redisProperties.getPassword())
+			.setTimeout(singleServerConfig.getTimeout())
+			.setRetryAttempts(singleServerConfig.getRetryAttempts())
+			.setRetryInterval(singleServerConfig.getRetryInterval())
+			.setSubscriptionsPerConnection(singleServerConfig.getSubscriptionsPerConnection())
+			.setClientName(singleServerConfig.getClientName())
+			.setIdleConnectionTimeout(singleServerConfig.getIdleConnectionTimeout())
+			.setSubscriptionConnectionMinimumIdleSize(singleServerConfig.getSubscriptionConnectionMinimumIdleSize())
+			.setSubscriptionConnectionPoolSize(singleServerConfig.getSubscriptionConnectionPoolSize())
+			.setConnectionMinimumIdleSize(singleServerConfig.getConnectionMinimumIdleSize())
+			.setConnectionPoolSize(singleServerConfig.getConnectionPoolSize())
+			.setDnsMonitoringInterval(singleServerConfig.getDnsMonitoringInterval());
+		return Redisson.create(config);
+	}
 }

+ 101 - 0
ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/RedissonProperties.java

@@ -0,0 +1,101 @@
+package com.ruoyi.framework.config.properties;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.redisson.client.codec.Codec;
+import org.redisson.config.TransportMode;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * Redisson 配置属性
+ *
+ * @author Lion Li
+ */
+@Data
+@Component
+@ConfigurationProperties(prefix = "redisson")
+public class RedissonProperties {
+
+	/**
+	 * 线程池数量,默认值 = 当前处理核数量 * 2
+	 */
+	private int threads;
+
+	/**
+	 * Netty线程池数量,默认值 = 当前处理核数量 * 2
+	 */
+	private int nettyThreads;
+
+	/**
+	 * 传输模式
+	 */
+	private TransportMode transportMode;
+
+	/**
+	 * 单机服务配置
+	 */
+	private SingleServerConfig singleServerConfig;
+
+	@Data
+	@NoArgsConstructor
+	public static class SingleServerConfig {
+
+		/**
+		 * 客户端名称
+		 */
+		private String clientName;
+
+		/**
+		 * 最小空闲连接数
+		 */
+		private int connectionMinimumIdleSize;
+
+		/**
+		 * 连接池大小
+		 */
+		private int connectionPoolSize;
+
+		/**
+		 * 连接空闲超时,单位:毫秒
+		 */
+		private int idleConnectionTimeout;
+
+		/**
+		 * 命令等待超时,单位:毫秒
+		 */
+		private int timeout;
+
+		/**
+		 * 如果尝试在此限制之内发送成功,则开始启用 timeout 计时。
+		 */
+		private int retryAttempts;
+
+		/**
+		 * 命令重试发送时间间隔,单位:毫秒
+		 */
+		private int retryInterval;
+
+		/**
+		 * 发布和订阅连接的最小空闲连接数
+		 */
+		private int subscriptionConnectionMinimumIdleSize;
+
+		/**
+		 * 发布和订阅连接池大小
+		 */
+		private int subscriptionConnectionPoolSize;
+
+		/**
+		 * 单个连接最大订阅数量
+		 */
+		private int subscriptionsPerConnection;
+
+		/**
+		 * DNS监测时间间隔,单位:毫秒
+		 */
+		private int dnsMonitoringInterval;
+
+	}
+
+}