目录
一、Redis单例模式
二、Redis哨兵模式
三、Redis集群模式
四、主从模式
五、兼容多种模式的配置(重点)
1、pom
2、配置文件
(1)application.properties
(2)application-dev.properties
(3) application-prod.properties
3、Java配置类
4、应用
<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.15.5</version>
</dependency><!--<dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.15.5</version>
</dependency>
-->
支持Redis多种连接模式,这里以RedissonClient工具为例
一、Redis单例模式
#单机模式
#Redis url should start with redis:// or rediss:// (for SSL connection)
my.redisson.address = redis://127.0.0.1:6379
my.redisson.password = wtyy
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class RedissionConfig {@Value("${my.redisson.address}")private String address;@Value("${my.redisson.password}")private String password;/*** 所有对Redisson的使用都是通过RedissonClient对象*/@Bean(destroyMethod = "shutdown")public RedissonClient redissonClient(){// 创建配置 指定redis地址及节点信息Config config = new Config();config.useSingleServer().setAddress(address);//.setPassword(password);// 根据config创建出RedissonClient实例RedissonClient redissonClient = Redisson.create(config);return redissonClient;}
}
二、Redis哨兵模式
my.redisson.sentinel.schema=
my.redisson.sentinel.address = redis://xxx.xx.xxx1:19601,redis://xxx.xx.xxx2:19601,redis://xxx.xx.xxx3:19601
my.redisson.sentinel.password = N5WAXX4z9qw
my.redisson.sentinel.master = master-test
my.redisson.sentinel.database = 10
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class RedissionConfig {@Value("${my.redisson.sentinel.address}")private String address;@Value("${my.redisson.sentinel.password}")private String password;@Value("${my.redisson.sentinel.master}")private String master;@Value("${my.redisson.sentinel.database}")private Integer dataBase;@Value("${my.redisson.sentinel.schema}")private String schema;/*** 所有对Redisson的使用都是通过RedissonClient对象*/@Bean(destroyMethod = "shutdown")public RedissonClient redissonClient(){Config config = new Config();config.useSentinelServers().setScanInterval(2000) // cluster state scan interval in milliseconds.addSentinelAddress(address.split(",")).setCheckSentinelsList(false).setMasterName(master).setPassword(password).setDatabase(dataBase);RedissonClient redissonClient = Redisson.create(config);return redissonClient;}
}
三、Redis集群模式
Config config = new Config();config.useClusterServers().setScanInterval(2000) // cluster state scan interval in milliseconds.addNodeAddress("redis://127.0.0.1:7000", "redis://127.0.0.1:7001").addNodeAddress("redis://127.0.0.1:7002");RedissonClient redisson = Redisson.create(config);
四、主从模式
Config config = new Config();config.useMasterSlaveServers().setMasterAddress("redis://127.0.0.1:6379").addSlaveAddress("redis://127.0.0.1:6389", "redis://127.0.0.1:6332", "redis://127.0.0.1:6419").addSlaveAddress("redis://127.0.0.1:6399");RedissonClient redisson = Redisson.create(config);
五、兼容多种模式的配置(重点)
从上面可以看到,不同的redis模式有不同的连接配置方式,如果连接变更,配置代码也要跟着变更,不够灵活,再比如有多套环境,测试环境和生产环境使用的是不同的redis模式,所以需要考虑配置兼容问题。下面的配置适用于所有模式。
1、pom
因为使用到了 RedisProperties,所以需要引入 spring-boot-starter-data-redis
<?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"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>redis-demo</artifactId><version>1.0-SNAPSHOT</version><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.2.4</version><relativePath/></parent><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.26.0</version></dependency><!--连接池依赖--><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId><version>2.11.1</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><scope>test</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!--hutool工具--><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.15</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.83</version></dependency><dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId><version>2.10.1</version></dependency></dependencies></project>
2、配置文件
按照 org.springframework.boot.autoconfigure.data.redis.RedisProperties 规则配置。源码:
package org.springframework.boot.autoconfigure.data.redis;@ConfigurationProperties(prefix = "spring.data.redis"
)
public class RedisProperties {private int database = 0;private String url;private String host = "localhost";private String username;private String password;private int port = 6379;private Duration timeout;private Duration connectTimeout;private String clientName;private ClientType clientType;private Sentinel sentinel;private Cluster cluster;private final Ssl ssl = new Ssl();private final Jedis jedis = new Jedis();private final Lettuce lettuce = new Lettuce();......
}
这里有两套环境:dev和prod
(1)application.properties
spring.profiles.active=dev
(2)application-dev.properties
spring.data.redis.host=127.0.0.1
spring.data.redis.port=6379
spring.data.redis.password=
spring.data.redis.lettuce.pool.max-active=8
spring.data.redis.lettuce.pool.max-wait=-1
spring.data.redis.lettuce.pool.max-idle=8
spring.data.redis.lettuce.pool.min-idle=0
spring.data.redis.lettuce.pool.enabled=true
spring.data.redis.lettuce.pool.time-between-eviction-runs=30s
(3) application-prod.properties
spring.data.redis.cluster.nodes=xxx.xxx.xx.xxx:6379
spring.data.redis.cluster.max-redirects=3
spring.data.redis.timeout=60S
spring.data.redis.lettuce.pool.max-wait=2S
spring.data.redis.lettuce.pool.max-active=1200
spring.data.redis.lettuce.pool.max-idle=400
spring.data.redis.lettuce.pool.min-idle=50
# spring.redis.lettuce.pool.time-between-eviction-runs=200
spring.data.redis.lettuce.pool.enabled=true
spring.data.redis.lettuce.pool.time-between-eviction-runs=30s
spring.data.redis.lettuce.cluster.refresh.adaptive=true
spring.data.redis.lettuce.cluster.refresh.period=60s
3、Java配置类
读取配置文件中 spring.data.redis 开头的配置,并加以判断。
package org.example.config;import io.micrometer.common.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;@Slf4j
@Configuration
public class RedissonConfig {@AutowiredRedisProperties redisProperties;private static final String REDIS_PROTOCOL_PREFIX = "redis://";private static final String REDISS_PROTOCOL_PREFIX = "rediss://";@Bean(destroyMethod = "shutdown")public RedissonClient redisson() {Config config;Method clusterMethod = ReflectionUtils.findMethod(RedisProperties.class, "getCluster");Method timeoutMethod = ReflectionUtils.findMethod(RedisProperties.class, "getTimeout");Object timeoutValue = ReflectionUtils.invokeMethod(timeoutMethod, redisProperties);int timeout;if (null == timeoutValue) {timeout = 10000;} else if (!(timeoutValue instanceof Integer)) {Method millisMethod = ReflectionUtils.findMethod(timeoutValue.getClass(), "toMillis");timeout = ((Long) ReflectionUtils.invokeMethod(millisMethod, timeoutValue)).intValue();} else {timeout = (Integer) timeoutValue;}if (redisProperties.getSentinel() != null) {Method nodesMethod =ReflectionUtils.findMethod(RedisProperties.Sentinel.class, "getNodes");Object nodesValue =ReflectionUtils.invokeMethod(nodesMethod, redisProperties.getSentinel());String[] nodes;if (nodesValue instanceof String) {nodes = convert(Arrays.asList(((String) nodesValue).split(",")));} else {nodes = convert((List<String>) nodesValue);}config = new Config();config.useSentinelServers().setMasterName(redisProperties.getSentinel().getMaster()).addSentinelAddress(nodes).setDatabase(redisProperties.getDatabase()).setConnectTimeout(timeout).setPassword(redisProperties.getPassword());} else if (clusterMethod != null&& ReflectionUtils.invokeMethod(clusterMethod, redisProperties) != null) {Object clusterObject = ReflectionUtils.invokeMethod(clusterMethod, redisProperties);Method nodesMethod = ReflectionUtils.findMethod(clusterObject.getClass(), "getNodes");List<String> nodesObject =(List) ReflectionUtils.invokeMethod(nodesMethod, clusterObject);String[] nodes = convert(nodesObject);config = new Config();config.useClusterServers().addNodeAddress(nodes).setConnectTimeout(timeout).setPassword(redisProperties.getPassword());} else {config = new Config();String prefix = REDIS_PROTOCOL_PREFIX;Method method = ReflectionUtils.findMethod(RedisProperties.class, "isSsl");if (method != null && (Boolean) ReflectionUtils.invokeMethod(method, redisProperties)) {prefix = REDISS_PROTOCOL_PREFIX;}String password =StringUtils.isBlank(redisProperties.getPassword())? null: redisProperties.getPassword();config.useSingleServer().setAddress(prefix + redisProperties.getHost() + ":" + redisProperties.getPort()).setConnectTimeout(timeout).setDatabase(redisProperties.getDatabase()).setPassword(password);}return Redisson.create(config);}private String[] convert(List<String> nodesObject) {List<String> nodes = new ArrayList<String>(nodesObject.size());for (String node : nodesObject) {if (!node.startsWith(REDIS_PROTOCOL_PREFIX)&& !node.startsWith(REDISS_PROTOCOL_PREFIX)) {nodes.add(REDIS_PROTOCOL_PREFIX + node);} else {nodes.add(node);}}return nodes.toArray(new String[nodes.size()]);}
}
这里用了反射,其实RedisProperties对象已经拿到了,直接从 redisProperties中get也是可以的:
RedisProperties.Cluster cluster = redisProperties.getCluster();
4、应用
import com.alibaba.fastjson.JSON;
import org.example.dto.UserDTO;
import org.example.service.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;@SpringBootTest(classes = {Main.class}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@RunWith(SpringRunner.class)
public class RedissonTest {@Autowiredprivate RedissonClient redissonClient;@Testpublic void testString(){RBucket<Object> bucket = redissonClient.getBucket("test");bucket.set("这是value");System.out.println(bucket.get());}
}
5、与RedisTemplate并存使用
这个demo引入了 spring-boot-starter-data-redis,所以可以直接使用RedisTemplate:
@SpringBootTest(classes = {Main.class}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@RunWith(SpringRunner.class)
public class MyTest {@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Autowiredprivate UserService userService;@Testpublic void testString(){String key = "string-name";//存String value = "这是value123";stringRedisTemplate.opsForValue().set(key,value);//取Object valueObj = stringRedisTemplate.opsForValue().get(key);System.out.println("value为:" + valueObj);}
}