Loading... 介绍:配置文件中可根据是否配置了哨兵模式,如果配置了则按照哨兵模式运行,如果没有配置哨兵模式,则按照单机模式运行。 ## 一、引入依赖 ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <exclusions> <exclusion> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> </exclusion> <exclusion> <groupId>io.lettuce</groupId> <artifactId>lettuce-core</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>${redis.version}</version> </dependency> ``` ## 二、配置文件 ```yaml spring: redis: host: 172.100.xxx.xxx #单机模式,哨兵模式可不配置 port: 6379 #单机模式,哨兵模式可不配置 password: xxxx timeout: 10000 database: 2 lettuce: pool: max-active: 180 #连接池最大连接数(使用负值表示没有限制) max-idle: 10 #连接池中的最大空闲连接 max-wait: 1500 #连接池最大阻塞等待时间(使用负值表示没有限制) # 哨兵模式,单机模式不要配置(配置文件中可根据是否配置了哨兵模式,如果配置了则按照哨兵模式运行,如果没有配置哨兵模式,则按照单机模式运行) sentinel: master: mymaster nodes: 172.100.xxx.xxx:27001,172.100.xxx.xxx:27002,172.100.xxx.xxx:27003 ``` ## 三、配置类 ```java import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisNode; import org.springframework.data.redis.connection.RedisSentinelConfiguration; import org.springframework.data.redis.connection.RedisStandaloneConfiguration; import org.springframework.data.redis.connection.jedis.JedisClientConfiguration; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.StringRedisSerializer; import redis.clients.jedis.JedisPoolConfig; import java.time.Duration; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; @Configuration @EnableAutoConfiguration public class RedisConfig { @Value("${spring.redis.host:}") private String host; @Value("${spring.redis.port:6379}") private int port; @Value("${spring.redis.timeout:10000}") private int timeout; @Value("${spring.redis.lettuce.pool.max-idle:10}") private int maxIdle; @Value("${spring.redis.lettuce.pool.max-wait:1500}") private long maxWaitMillis; @Value("${spring.redis.lettuce.pool.max-active:180}") private int maxActive; @Value("${spring.redis.password:}") private String password; @Value("${spring.redis.database:}") private String database; @Value("${spring.redis.sentinel.nodes:}") private String nodes; @Value("${spring.redis.sentinel.master:}") private String master; @Bean @ConfigurationProperties(prefix="spring.redis") public JedisPoolConfig getRedisConfig(){ JedisPoolConfig config = new JedisPoolConfig(); config.setMaxIdle(maxIdle); config.setMaxWaitMillis(maxWaitMillis); config.setMaxTotal(maxActive); return config; } // @Bean // public RedisSentinelConfiguration sentinelConfiguration(){ // RedisSentinelConfiguration redisSentinelConfiguration = new RedisSentinelConfiguration(); // //配置matser的名称 // redisSentinelConfiguration.master(master); // //配置redis的哨兵sentinel // Set<RedisNode> redisNodeSet = new HashSet<>(); // if (StringUtils.isNotBlank(master) && StringUtils.isNotBlank(nodes)) { // String[] nodeSplit = nodes.split(","); // List<String> nodeList = Arrays.asList(nodeSplit); // nodeList.forEach(x->{ // redisNodeSet.add(new RedisNode(x.split(":")[0],Integer.parseInt(x.split(":")[1]))); // }); // } // redisSentinelConfiguration.setSentinels(redisNodeSet); redisSentinelConfiguration.setSentinelPassword(password); // return redisSentinelConfiguration; // } @Bean public JedisConnectionFactory jedisConnectionFactory(JedisPoolConfig jedisPoolConfig) { JedisConnectionFactory jedisConnectionFactory = null; //判断redis是单机模式还是哨兵模式 if (StringUtils.isBlank(master) || StringUtils.isBlank(nodes)) { RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(); redisStandaloneConfiguration.setHostName(host); redisStandaloneConfiguration.setPassword(password); redisStandaloneConfiguration.setDatabase(Integer.parseInt(database)); redisStandaloneConfiguration.setPort(port); JedisClientConfiguration.JedisClientConfigurationBuilder jedisClientConfiguration = JedisClientConfiguration.builder(); jedisClientConfiguration.connectTimeout(Duration.ofMillis(timeout)); JedisClientConfiguration jedisClientConfigurationNew = jedisClientConfiguration.usePooling().poolConfig(jedisPoolConfig).build(); jedisConnectionFactory = new JedisConnectionFactory(redisStandaloneConfiguration,jedisClientConfigurationNew); } else { RedisSentinelConfiguration redisSentinelConfiguration = new RedisSentinelConfiguration(); //配置matser的名称 redisSentinelConfiguration.master(master); //配置redis的哨兵sentinel Set<RedisNode> redisNodeSet = new HashSet<>(); if (StringUtils.isNotBlank(nodes)) { String[] nodeSplit = nodes.split(","); List<String> nodeList = Arrays.asList(nodeSplit); nodeList.forEach(x->{ redisNodeSet.add(new RedisNode(x.split(":")[0],Integer.parseInt(x.split(":")[1]))); }); } redisSentinelConfiguration.setSentinels(redisNodeSet); redisSentinelConfiguration.setPassword(password); jedisConnectionFactory = new JedisConnectionFactory(redisSentinelConfiguration,jedisPoolConfig); } return jedisConnectionFactory; } @Bean public RedisTemplate<String, Object> redisTemplate(JedisConnectionFactory jedisConnectionFactory) { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); redisTemplate.setHashValueSerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(new StringRedisSerializer()); redisTemplate.setConnectionFactory(jedisConnectionFactory); return redisTemplate; } } ``` ## 四、RedisTemplate测试 ```java import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.test.context.junit4.SpringRunner; @SpringBootTest(classes = Application.class) @RunWith(SpringRunner.class) public class MyApplicationTest { @Autowired private RedisTemplate<String, Object> redisTemplate; @Test public void contextLoads() { // 测试内容 redisTemplate.opsForValue().set("test", "test"); } @Test public void contextGets() { // 测试内容 System.out.println(redisTemplate.opsForValue().get("test")); } } ``` ## 五、低版本配置 我在项目部署中如果使用低版本Spring boot可能会出现一些配置类不存在等情况,比如我使用spring-boot:1.5.4.RELEASE,那么 就会缺少 ```java import org.springframework.data.redis.connection.RedisStandaloneConfiguration; import org.springframework.data.redis.connection.jedis.JedisClientConfiguration; ``` 这两个配置,而且还会存在依赖冲突,版本不匹配,我们修改依赖如下: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <exclusions> <exclusion> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> </exclusion> <exclusion> <groupId>io.lettuce</groupId> <artifactId>lettuce-core</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.3</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>1.7.11.RELEASE</version> </dependency> ``` yaml ```yaml spring: redis: host: 172.100.xxx.xxx #单机模式,哨兵模式可不配置 port: 6379 #单机模式,哨兵模式可不配置 password: xxxx timeout: 10000 database: 2 lettuce: pool: max-active: 180 #连接池最大连接数(使用负值表示没有限制) max-idle: 10 #连接池中的最大空闲连接 max-wait: 1500 #连接池最大阻塞等待时间(使用负值表示没有限制) # 哨兵模式,单机模式不要配置(配置文件中可根据是否配置了哨兵模式,如果配置了则按照哨兵模式运行,如果没有配置哨兵模式,则按照单机模式运行) sentinel: master: mymaster nodes: 172.100.xxx.xxx:27001,172.100.xxx.xxx:27002,172.100.xxx.xxx:27003 password: Topway12#$ ``` 修改RedisConfig.java中的配置,我这里哨兵也配置了密码。 ```java package com.tw.nms.fttx.config; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisNode; import org.springframework.data.redis.connection.RedisSentinelConfiguration; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.StringRedisSerializer; import redis.clients.jedis.JedisPoolConfig; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; @Configuration @EnableAutoConfiguration public class RedisSentinelAndStandaloneConfig { @Value("${spring.redis.host:}") private String host; @Value("${spring.redis.port:6379}") private int port; @Value("${spring.redis.timeout:10000}") private int timeout; @Value("${spring.redis.lettuce.pool.max-idle:10}") private int maxIdle; @Value("${spring.redis.lettuce.pool.max-wait:1500}") private long maxWaitMillis; @Value("${spring.redis.lettuce.pool.max-active:180}") private int maxActive; @Value("${spring.redis.password:}") private String password; @Value("${spring.redis.database:}") private String database; @Value("${spring.redis.sentinel.nodes:}") private String nodes; @Value("${spring.redis.sentinel.master:}") private String master; @Value("${spring.redis.sentinel.password:}") private String sentinelPassword; @Bean("JedisPoolConfig") @ConfigurationProperties(prefix = "spring.redis") public JedisPoolConfig getRedisConfig() { JedisPoolConfig config = new JedisPoolConfig(); config.setMaxIdle(maxIdle); config.setMaxWaitMillis(maxWaitMillis); config.setMaxTotal(maxActive); return config; } @Bean public JedisConnectionFactory jedisConnectionFactory(@Qualifier("JedisPoolConfig") JedisPoolConfig jedisPoolConfig) { JedisConnectionFactory jedisConnectionFactory = null; //判断redis是单机模式还是哨兵模式 if (StringUtils.isBlank(master) || StringUtils.isBlank(nodes)) { jedisConnectionFactory = new JedisConnectionFactory(); jedisConnectionFactory.setHostName(host); jedisConnectionFactory.setPort(port); jedisConnectionFactory.setTimeout(timeout); jedisConnectionFactory.setPassword(password); jedisConnectionFactory.setDatabase(Integer.parseInt(database)); jedisConnectionFactory.setPoolConfig(jedisPoolConfig); } else { //哨兵模式,设置密码 RedisSentinelConfiguration redisSentinelConfiguration = new RedisSentinelConfiguration(); redisSentinelConfiguration.setMaster(master); Set<RedisNode> redisNodeSet = new HashSet<>(); List<String> nodeList = Arrays.asList(nodes.split(",")); for (String node : nodeList) { String[] nodeArray = node.split(":"); redisNodeSet.add(new RedisNode(nodeArray[0], Integer.parseInt(nodeArray[1]))); } redisSentinelConfiguration.setSentinels(redisNodeSet); jedisConnectionFactory = new JedisConnectionFactory(redisSentinelConfiguration, jedisPoolConfig); jedisConnectionFactory.setPassword(sentinelPassword); } return jedisConnectionFactory; } @Bean public RedisTemplate<String, Object> redisTemplate(JedisConnectionFactory jedisConnectionFactory) { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); redisTemplate.setHashValueSerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(new StringRedisSerializer()); redisTemplate.setConnectionFactory(jedisConnectionFactory); return redisTemplate; } } ``` ## 五、改进:哨兵节点不可用则切换为单机节点 如果同时配置哨兵节点和单机节点,当哨兵节点不可用,则自适应选择单机节点 ```java package com.nms.tr069.config; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisNode; import org.springframework.data.redis.connection.RedisSentinelConfiguration; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.StringRedisSerializer; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPoolConfig; import redis.clients.jedis.exceptions.JedisException; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; @Slf4j @Configuration @EnableAutoConfiguration public class RedisSentinelAndStandaloneConfig { @Value("${spring.redis.host:}") private String host; @Value("${spring.redis.port:6379}") private int port; @Value("${spring.redis.timeout:10000}") private int timeout; @Value("${spring.redis.lettuce.pool.max-idle:10}") private int maxIdle; @Value("${spring.redis.lettuce.pool.max-wait:1500}") private long maxWaitMillis; @Value("${spring.redis.lettuce.pool.max-active:180}") private int maxActive; @Value("${spring.redis.password:}") private String password; @Value("${spring.redis.database:}") private String database; @Value("${spring.redis.sentinel.nodes:}") private String nodes; @Value("${spring.redis.sentinel.master:}") private String master; @Value("${spring.redis.sentinel.password:}") private String sentinelPassword; @Bean("JedisPoolConfig") @ConfigurationProperties(prefix = "spring.redis") public JedisPoolConfig getRedisConfig() { JedisPoolConfig config = new JedisPoolConfig(); config.setMaxIdle(maxIdle); config.setMaxWaitMillis(maxWaitMillis); config.setMaxTotal(maxActive); return config; } @Bean public JedisConnectionFactory jedisConnectionFactory(@Qualifier("JedisPoolConfig") JedisPoolConfig jedisPoolConfig) { JedisConnectionFactory jedisConnectionFactory = null; //判断redis是否配置了哨兵节点 if (StringUtils.isBlank(master) || StringUtils.isBlank(nodes)) { jedisConnectionFactory = new JedisConnectionFactory(); jedisConnectionFactory.setHostName(host); jedisConnectionFactory.setPort(port); jedisConnectionFactory.setTimeout(timeout); jedisConnectionFactory.setPassword(password); jedisConnectionFactory.setDatabase(Integer.parseInt(database)); jedisConnectionFactory.setPoolConfig(jedisPoolConfig); } else { //哨兵模式 RedisSentinelConfiguration redisSentinelConfiguration = new RedisSentinelConfiguration(); redisSentinelConfiguration.setMaster(master); Set<RedisNode> redisNodeSet = new HashSet<>(); List<String> nodeList = Arrays.asList(nodes.split(",")); for (String node : nodeList) { String[] nodeArray = node.split(":"); redisNodeSet.add(new RedisNode(nodeArray[0], Integer.parseInt(nodeArray[1]))); } redisSentinelConfiguration.setSentinels(redisNodeSet); // 尝试连接到所有哨兵节点,如果所有哨兵节点都不可用,则选择单机节点 boolean sentinelAvailable = false; for (RedisNode redisNode : redisNodeSet) { try { Jedis jedis = new Jedis(redisNode.getHost(), redisNode.getPort()); jedis.connect(); sentinelAvailable = true; jedis.disconnect(); break; } catch (JedisException e) { log.error("redis sentinel node {}:{} is not available", redisNode.getHost(), redisNode.getPort()); log.error(e.getMessage(), e); } } if (sentinelAvailable) { jedisConnectionFactory = new JedisConnectionFactory(redisSentinelConfiguration, jedisPoolConfig); jedisConnectionFactory.setPassword(sentinelPassword); } else { // 哨兵节点不可用,选择单机节点 jedisConnectionFactory = new JedisConnectionFactory(); jedisConnectionFactory.setHostName(host); jedisConnectionFactory.setPort(port); jedisConnectionFactory.setTimeout(timeout); jedisConnectionFactory.setPassword(password); jedisConnectionFactory.setDatabase(Integer.parseInt(database)); jedisConnectionFactory.setPoolConfig(jedisPoolConfig); } } return jedisConnectionFactory; } @Bean public RedisTemplate<String, Object> redisTemplate(JedisConnectionFactory jedisConnectionFactory) { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); redisTemplate.setHashValueSerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(new StringRedisSerializer()); redisTemplate.setConnectionFactory(jedisConnectionFactory); return redisTemplate; } } ``` 最后修改:2023 年 11 月 10 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 1 如果觉得我的文章对你有用,请随意赞赏