From b3f5b28037fff8b2108368480fef31c2948069b1 Mon Sep 17 00:00:00 2001 From: liuxiaolong Date: Tue, 20 May 2025 14:38:24 +0800 Subject: [PATCH] =?UTF-8?q?Redis=E6=8F=92=E4=BB=B6=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E4=B8=BB=E4=BB=8E=E6=A8=A1=E5=BC=8F=E4=B8=B6=E5=93=A8=E5=85=B5?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F=E4=B8=B6=E4=BA=91=E6=89=98=E7=AE=A1=E6=A8=A1?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application-dev.yml | 14 +- .../src/main/resources/application-prod.yml | 14 +- .../java/org/dromara/common/redis/Model.java | 15 ++ .../common/redis/config/RedisConfig.java | 166 +++++++++++++++--- .../config/properties/RedissonProperties.java | 113 ++++++++---- 5 files changed, 253 insertions(+), 69 deletions(-) create mode 100644 ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/Model.java diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml index 5dd2e00fe..d3e5f6813 100644 --- a/ruoyi-admin/src/main/resources/application-dev.yml +++ b/ruoyi-admin/src/main/resources/application-dev.yml @@ -112,24 +112,26 @@ spring.data: # redisson 配置 redisson: + # 模式 org.dromara.common.redis.Model + model: SINGLE # redis key前缀 keyPrefix: # 线程池数量 threads: 4 # Netty线程池数量 nettyThreads: 8 + # 客户端名称 不能用中文 + clientName: RuoYi-Vue-Plus + # 连接空闲超时,单位:毫秒 + idleConnectionTimeout: 10000 + # 命令等待超时,单位:毫秒 + timeout: 3000 # 单节点配置 singleServerConfig: - # 客户端名称 不能用中文 - clientName: RuoYi-Vue-Plus # 最小空闲连接数 connectionMinimumIdleSize: 8 # 连接池大小 connectionPoolSize: 32 - # 连接空闲超时,单位:毫秒 - idleConnectionTimeout: 10000 - # 命令等待超时,单位:毫秒 - timeout: 3000 # 发布和订阅连接池大小 subscriptionConnectionPoolSize: 50 diff --git a/ruoyi-admin/src/main/resources/application-prod.yml b/ruoyi-admin/src/main/resources/application-prod.yml index 435a9e856..683cb8a12 100644 --- a/ruoyi-admin/src/main/resources/application-prod.yml +++ b/ruoyi-admin/src/main/resources/application-prod.yml @@ -115,24 +115,26 @@ spring.data: # redisson 配置 redisson: + # 模式 org.dromara.common.redis.Model + model: SINGLE # redis key前缀 keyPrefix: # 线程池数量 threads: 16 # Netty线程池数量 nettyThreads: 32 + # 客户端名称 不能用中文 + clientName: RuoYi-Vue-Plus + # 连接空闲超时,单位:毫秒 + idleConnectionTimeout: 10000 + # 命令等待超时,单位:毫秒 + timeout: 3000 # 单节点配置 singleServerConfig: - # 客户端名称 不能用中文 - clientName: RuoYi-Vue-Plus # 最小空闲连接数 connectionMinimumIdleSize: 32 # 连接池大小 connectionPoolSize: 64 - # 连接空闲超时,单位:毫秒 - idleConnectionTimeout: 10000 - # 命令等待超时,单位:毫秒 - timeout: 3000 # 发布和订阅连接池大小 subscriptionConnectionPoolSize: 50 diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/Model.java b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/Model.java new file mode 100644 index 000000000..9f0f08af3 --- /dev/null +++ b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/Model.java @@ -0,0 +1,15 @@ +package org.dromara.common.redis; + +public enum Model { + + //单例 + SINGLE, + //集群 + CLUSTER, + //哨兵 + SENTINEL, + //主从 + MASTER_SLAVE, + //云托管模式 + REPLICATED +} diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/config/RedisConfig.java b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/config/RedisConfig.java index 7ba94751a..8f92f0c74 100644 --- a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/config/RedisConfig.java +++ b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/config/RedisConfig.java @@ -1,6 +1,5 @@ package org.dromara.common.redis.config; -import cn.hutool.core.util.ObjectUtil; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; @@ -16,12 +15,17 @@ import org.dromara.common.redis.handler.RedisExceptionHandler; import org.redisson.client.codec.StringCodec; import org.redisson.codec.CompositeCodec; import org.redisson.codec.TypedJsonJacksonCodec; +import org.redisson.config.MasterSlaveServersConfig; +import org.redisson.config.ReplicatedServersConfig; +import org.redisson.config.SentinelServersConfig; +import org.redisson.connection.balancer.LoadBalancer; import org.redisson.spring.starter.RedissonAutoConfigurationCustomizer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.core.task.VirtualThreadTaskExecutor; +import org.springframework.util.StringUtils; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; @@ -68,39 +72,140 @@ public class RedisConfig { config.setNettyExecutor(new VirtualThreadTaskExecutor("redisson-")); } RedissonProperties.SingleServerConfig singleServerConfig = redissonProperties.getSingleServerConfig(); - if (ObjectUtil.isNotNull(singleServerConfig)) { - // 使用单机模式 - config.useSingleServer() - //设置redis key前缀 - .setNameMapper(new KeyPrefixHandler(redissonProperties.getKeyPrefix())) - .setTimeout(singleServerConfig.getTimeout()) - .setClientName(singleServerConfig.getClientName()) - .setIdleConnectionTimeout(singleServerConfig.getIdleConnectionTimeout()) - .setSubscriptionConnectionPoolSize(singleServerConfig.getSubscriptionConnectionPoolSize()) - .setConnectionMinimumIdleSize(singleServerConfig.getConnectionMinimumIdleSize()) - .setConnectionPoolSize(singleServerConfig.getConnectionPoolSize()); - } // 集群配置方式 参考下方注释 RedissonProperties.ClusterServersConfig clusterServersConfig = redissonProperties.getClusterServersConfig(); - if (ObjectUtil.isNotNull(clusterServersConfig)) { - config.useClusterServers() - //设置redis key前缀 - .setNameMapper(new KeyPrefixHandler(redissonProperties.getKeyPrefix())) - .setTimeout(clusterServersConfig.getTimeout()) - .setClientName(clusterServersConfig.getClientName()) - .setIdleConnectionTimeout(clusterServersConfig.getIdleConnectionTimeout()) - .setSubscriptionConnectionPoolSize(clusterServersConfig.getSubscriptionConnectionPoolSize()) - .setMasterConnectionMinimumIdleSize(clusterServersConfig.getMasterConnectionMinimumIdleSize()) - .setMasterConnectionPoolSize(clusterServersConfig.getMasterConnectionPoolSize()) - .setSlaveConnectionMinimumIdleSize(clusterServersConfig.getSlaveConnectionMinimumIdleSize()) - .setSlaveConnectionPoolSize(clusterServersConfig.getSlaveConnectionPoolSize()) - .setReadMode(clusterServersConfig.getReadMode()) - .setSubscriptionMode(clusterServersConfig.getSubscriptionMode()); + switch (redissonProperties.getModel()){ + case SINGLE: + // 使用单机模式 + config.useSingleServer() + //设置redis key前缀 + .setNameMapper(new KeyPrefixHandler(redissonProperties.getKeyPrefix())) + .setTimeout(redissonProperties.getTimeout()) + .setClientName(redissonProperties.getClientName()) + .setIdleConnectionTimeout(redissonProperties.getIdleConnectionTimeout()) + .setSubscriptionConnectionPoolSize(singleServerConfig.getSubscriptionConnectionPoolSize()) + .setConnectionMinimumIdleSize(singleServerConfig.getConnectionMinimumIdleSize()) + .setConnectionPoolSize(singleServerConfig.getConnectionPoolSize()); + break; + case CLUSTER: + config.useClusterServers() + //设置redis key前缀 + .setNameMapper(new KeyPrefixHandler(redissonProperties.getKeyPrefix())) + .setTimeout(redissonProperties.getTimeout()) + .setClientName(redissonProperties.getClientName()) + .setIdleConnectionTimeout(redissonProperties.getIdleConnectionTimeout()) + .setSubscriptionConnectionPoolSize(clusterServersConfig.getSubscriptionConnectionPoolSize()) + .setMasterConnectionMinimumIdleSize(clusterServersConfig.getMasterConnectionMinimumIdleSize()) + .setMasterConnectionPoolSize(clusterServersConfig.getMasterConnectionPoolSize()) + .setSlaveConnectionMinimumIdleSize(clusterServersConfig.getSlaveConnectionMinimumIdleSize()) + .setSlaveConnectionPoolSize(clusterServersConfig.getSlaveConnectionPoolSize()) + .setReadMode(clusterServersConfig.getReadMode()) + .setSubscriptionMode(clusterServersConfig.getSubscriptionMode()); + break; + case SENTINEL: + SentinelServersConfig sentinelServersConfig = config.useSentinelServers(); + sentinelServersConfig.setNameMapper(new KeyPrefixHandler(redissonProperties.getKeyPrefix())); + sentinelServersConfig.setDatabase(clusterServersConfig.getDatabase()); + sentinelServersConfig.setMasterName(clusterServersConfig.getMasterName()); + sentinelServersConfig.setScanInterval(clusterServersConfig.getScanInterval()); + sentinelServersConfig.setSlaveConnectionMinimumIdleSize(clusterServersConfig.getSlaveConnectionMinimumIdleSize()); + sentinelServersConfig.setSlaveConnectionPoolSize(clusterServersConfig.getSlaveConnectionPoolSize()); + sentinelServersConfig.setFailedSlaveReconnectionInterval(clusterServersConfig.getFailedSlaveReconnectionInterval()); + sentinelServersConfig.setFailedSlaveCheckInterval(clusterServersConfig.getFailedSlaveCheckInterval()); + sentinelServersConfig.setMasterConnectionMinimumIdleSize(clusterServersConfig.getMasterConnectionMinimumIdleSize()); + sentinelServersConfig.setMasterConnectionPoolSize(clusterServersConfig.getMasterConnectionPoolSize()); + sentinelServersConfig.setReadMode(clusterServersConfig.getReadMode()); + sentinelServersConfig.setSubscriptionMode(clusterServersConfig.getSubscriptionMode()); + sentinelServersConfig.setSubscriptionConnectionMinimumIdleSize(clusterServersConfig.getSubscriptionConnectionMinimumIdleSize()); + sentinelServersConfig.setSubscriptionConnectionPoolSize(clusterServersConfig.getSubscriptionConnectionPoolSize()); + sentinelServersConfig.setDnsMonitoringInterval(clusterServersConfig.getDnsMonitoringInterval()); + try { + sentinelServersConfig.setLoadBalancer((LoadBalancer) Class.forName(clusterServersConfig.getLoadBalancer()).newInstance()); + } catch (Exception e) { + throw new RuntimeException(e); + } + for (String nodeAddress : clusterServersConfig.getNodeAddresses()) { + sentinelServersConfig.addSentinelAddress(prefixAddress(nodeAddress)); + } + sentinelServersConfig.setClientName(redissonProperties.getClientName()); + sentinelServersConfig.setConnectTimeout(redissonProperties.getConnectTimeout()); + sentinelServersConfig.setIdleConnectionTimeout(redissonProperties.getIdleConnectionTimeout()); + sentinelServersConfig.setTimeout(redissonProperties.getTimeout()); + break; + case MASTER_SLAVE: + MasterSlaveServersConfig masterSlaveServersConfig = config.useMasterSlaveServers(); + masterSlaveServersConfig.setNameMapper(new KeyPrefixHandler(redissonProperties.getKeyPrefix())); + masterSlaveServersConfig.setDatabase(clusterServersConfig.getDatabase()); + masterSlaveServersConfig.setSlaveConnectionMinimumIdleSize(clusterServersConfig.getSlaveConnectionMinimumIdleSize()); + masterSlaveServersConfig.setSlaveConnectionPoolSize(clusterServersConfig.getSlaveConnectionPoolSize()); + masterSlaveServersConfig.setFailedSlaveReconnectionInterval(clusterServersConfig.getFailedSlaveReconnectionInterval()); + masterSlaveServersConfig.setFailedSlaveCheckInterval(clusterServersConfig.getFailedSlaveCheckInterval()); + masterSlaveServersConfig.setMasterConnectionMinimumIdleSize(clusterServersConfig.getMasterConnectionMinimumIdleSize()); + masterSlaveServersConfig.setMasterConnectionPoolSize(clusterServersConfig.getMasterConnectionPoolSize()); + masterSlaveServersConfig.setReadMode(clusterServersConfig.getReadMode()); + masterSlaveServersConfig.setSubscriptionMode(clusterServersConfig.getSubscriptionMode()); + masterSlaveServersConfig.setSubscriptionConnectionMinimumIdleSize(clusterServersConfig.getSubscriptionConnectionMinimumIdleSize()); + masterSlaveServersConfig.setSubscriptionConnectionPoolSize(clusterServersConfig.getSubscriptionConnectionPoolSize()); + masterSlaveServersConfig.setDnsMonitoringInterval(clusterServersConfig.getDnsMonitoringInterval()); + try { + masterSlaveServersConfig.setLoadBalancer((LoadBalancer) Class.forName(clusterServersConfig.getLoadBalancer()).newInstance()); + } catch (Exception e) { + throw new RuntimeException(e); + } + int index=0; + for (String nodeAddress : clusterServersConfig.getNodeAddresses()) { + if(index++==0){ + masterSlaveServersConfig.setMasterAddress(prefixAddress(nodeAddress)); + }else{ + masterSlaveServersConfig.addSlaveAddress(prefixAddress(nodeAddress)); + } + } + masterSlaveServersConfig.setClientName(redissonProperties.getClientName()); + masterSlaveServersConfig.setConnectTimeout(redissonProperties.getConnectTimeout()); + masterSlaveServersConfig.setIdleConnectionTimeout(redissonProperties.getIdleConnectionTimeout()); + masterSlaveServersConfig.setTimeout(redissonProperties.getTimeout()); + break; + case REPLICATED: + ReplicatedServersConfig replicatedServersConfig = config.useReplicatedServers(); + replicatedServersConfig.setNameMapper(new KeyPrefixHandler(redissonProperties.getKeyPrefix())); + replicatedServersConfig.setDatabase(clusterServersConfig.getDatabase()); + replicatedServersConfig.setScanInterval(clusterServersConfig.getScanInterval()); + replicatedServersConfig.setSlaveConnectionMinimumIdleSize(clusterServersConfig.getSlaveConnectionMinimumIdleSize()); + replicatedServersConfig.setSlaveConnectionPoolSize(clusterServersConfig.getSlaveConnectionPoolSize()); + replicatedServersConfig.setFailedSlaveReconnectionInterval(clusterServersConfig.getFailedSlaveReconnectionInterval()); + replicatedServersConfig.setFailedSlaveCheckInterval(clusterServersConfig.getFailedSlaveCheckInterval()); + replicatedServersConfig.setMasterConnectionMinimumIdleSize(clusterServersConfig.getMasterConnectionMinimumIdleSize()); + replicatedServersConfig.setMasterConnectionPoolSize(clusterServersConfig.getMasterConnectionPoolSize()); + replicatedServersConfig.setReadMode(clusterServersConfig.getReadMode()); + replicatedServersConfig.setSubscriptionMode(clusterServersConfig.getSubscriptionMode()); + replicatedServersConfig.setSubscriptionConnectionMinimumIdleSize(clusterServersConfig.getSubscriptionConnectionMinimumIdleSize()); + replicatedServersConfig.setSubscriptionConnectionPoolSize(clusterServersConfig.getSubscriptionConnectionPoolSize()); + replicatedServersConfig.setDnsMonitoringInterval(clusterServersConfig.getDnsMonitoringInterval()); + try { + replicatedServersConfig.setLoadBalancer((LoadBalancer) Class.forName(clusterServersConfig.getLoadBalancer()).newInstance()); + } catch (Exception e) { + throw new RuntimeException(e); + } + for (String nodeAddress : clusterServersConfig.getNodeAddresses()) { + replicatedServersConfig.addNodeAddress(prefixAddress(nodeAddress)); + } + replicatedServersConfig.setClientName(redissonProperties.getClientName()); + replicatedServersConfig.setConnectTimeout(redissonProperties.getConnectTimeout()); + replicatedServersConfig.setIdleConnectionTimeout(redissonProperties.getIdleConnectionTimeout()); + replicatedServersConfig.setTimeout(redissonProperties.getTimeout()); + break; } log.info("初始化 redis 配置"); }; } + private String prefixAddress(String address){ + if(!StringUtils.isEmpty(address)&&!address.startsWith("redis")){ + return "redis://"+address; + } + return address; + } + /** * 异常处理器 */ @@ -134,6 +239,10 @@ public class RedisConfig { * nettyThreads: 32 * # 集群配置 * clusterServersConfig: + * node-addresses: + * - 127.0.0.1:6379 + * - 127.0.0.1:6380 + * - 127.0.0.1:6381 * # 客户端名称 * clientName: ${ruoyi.name} * # master最小空闲连接数 @@ -154,6 +263,9 @@ public class RedisConfig { * readMode: "SLAVE" * # 订阅模式 * subscriptionMode: "MASTER" + * #单Redis节点模式 + * singleServerConfig: + * address: 127.0.0.1:6379 */ } diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/config/properties/RedissonProperties.java b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/config/properties/RedissonProperties.java index ebec7861a..f3eeb5ce3 100644 --- a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/config/properties/RedissonProperties.java +++ b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/config/properties/RedissonProperties.java @@ -2,10 +2,14 @@ package org.dromara.common.redis.config.properties; import lombok.Data; import lombok.NoArgsConstructor; +import org.dromara.common.redis.Model; import org.redisson.config.ReadMode; import org.redisson.config.SubscriptionMode; import org.springframework.boot.context.properties.ConfigurationProperties; +import java.util.ArrayList; +import java.util.List; + /** * Redisson 配置属性 * @@ -15,6 +19,11 @@ import org.springframework.boot.context.properties.ConfigurationProperties; @ConfigurationProperties(prefix = "redisson") public class RedissonProperties { + /* + * 模式 + */ + private Model model= Model.SINGLE; + /** * redis缓存key前缀 */ @@ -30,6 +39,27 @@ public class RedissonProperties { */ private int nettyThreads; + /** + * 连接空闲超时,单位:毫秒 + */ + private int idleConnectionTimeout; + + /** + * 命令等待超时,单位:毫秒 + */ + private int timeout; + + /** + * 客户端名称 + */ + private String clientName; + + /* + * 连接超时,单位:毫秒 + */ + private Integer connectTimeout = 10000; + + /** * 单机服务配置 */ @@ -44,10 +74,6 @@ public class RedissonProperties { @NoArgsConstructor public static class SingleServerConfig { - /** - * 客户端名称 - */ - private String clientName; /** * 最小空闲连接数 @@ -59,16 +85,6 @@ public class RedissonProperties { */ private int connectionPoolSize; - /** - * 连接空闲超时,单位:毫秒 - */ - private int idleConnectionTimeout; - - /** - * 命令等待超时,单位:毫秒 - */ - private int timeout; - /** * 发布和订阅连接池大小 */ @@ -80,10 +96,6 @@ public class RedissonProperties { @NoArgsConstructor public static class ClusterServersConfig { - /** - * 客户端名称 - */ - private String clientName; /** * master最小空闲连接数 @@ -105,31 +117,72 @@ public class RedissonProperties { */ private int slaveConnectionPoolSize; - /** - * 连接空闲超时,单位:毫秒 - */ - private int idleConnectionTimeout; - - /** - * 命令等待超时,单位:毫秒 - */ - private int timeout; - /** * 发布和订阅连接池大小 */ private int subscriptionConnectionPoolSize; /** - * 读取模式 + * 设置读取操作选择节点的模式。 + * SLAVE - 只在从服务节点里读取。 + * MASTER - 只在主服务节点里读取。 + * MASTER_SLAVE - 在主从服务节点里都可以读取 */ private ReadMode readMode; /** - * 订阅模式 + * 设置订阅操作选择节点的模式。 + * SLAVE - 只在从服务节点里订阅。 + * MASTER - 只在主服务节点里订阅 */ private SubscriptionMode subscriptionMode; + /* + * 负载均衡方式 + */ + private String loadBalancer = "org.redisson.connection.balancer.RoundRobinLoadBalancer"; + + /* + * 订阅连接失败重连间隔时间 + */ + private Integer failedSlaveReconnectionInterval = 3000; + + /* + * 订阅连接空闲超时 + */ + private Integer failedSlaveCheckInterval = 180000; + + /* + * 用于发布和订阅连接的最小保持连接数(长连接) + */ + private Integer subscriptionConnectionMinimumIdleSize=1; + + /* + * 监测DNS的变化情况的时间间隔 + */ + private Long dnsMonitoringInterval=5000L; + + /* + * 节点地址 + */ + private List nodeAddresses = new ArrayList(); + + + /* + * (集群,哨兵,云托管模特特有) 对Redis集群节点状态扫描的时间间隔。单位是毫秒 + */ + private Integer scanInterval = 1000; + + /* + * (哨兵模式,云托管,主从模式特有)尝试连接的数据库编号 + */ + private Integer database = 0; + + /* + * (哨兵模式特有)主服务器的名称是哨兵进程中用来监测主从服务切换情况的 + */ + private String masterName; + } }