本文侧重于springboot集成,redis哨兵模式的搭建请参考其他文章。
一主二从redis和三个哨兵,springboot环境。
先写一个小demo来测试一个哨兵模式是否能够访问。
public class test1 {
public static void main(String[] args) throws Exception {
test1.testSentinel();
}
public static void testSentinel() throws Exception {
String masterName = "mymaster";
Set sentinels = new HashSet<>();
//三个哨兵
sentinels.add("127.0.0.1:26379");
sentinels.add("127.0.0.1:26380");
sentinels.add("127.0.0.1:26381");
JedisSentinelPool pool = new JedisSentinelPool(masterName, sentinels);
Jedis jedis = pool.getResource();
jedis.set("key1", "value1");
pool.close();
}
}
运行,我在调试过程中遇到的问题:
问题1:
All sentinels down, cannot determine where is mymaster master is running
解决方式:将redis哨兵配置文件的bind 127.0.0.1注释掉
问题2:
java.net.SocketException: Connection reset by peer: socket write error
解决方法:redis哨兵配置文件中新增一行 protected-mode no
表明不已保护模式运行。
更改完配置以后重启redis哨兵,运行正常,测试完毕。
接下来进行springboot集成。
pom依赖:
org.springframework.boot
spring-boot-starter-redis
1.4.7.RELEASE
两者不兼容或版本号不兼容
同时引入有可能会导致JedisConnectionFactory连接出错
redis配置:
@Configuration
@EnableAutoConfiguration
public class RedisConfig extends CachingConfigurerSupport {
private static Logger logger = LoggerFactory.getLogger(RedisConfig.class);
@Value("#{'${spring.redis.sentinel.nodes}'.split(',')}")
private List nodes;
@Value("${spring.redis.sentinel.nodes}")
private String redisNodes;
@Value("${spring.redis.sentinel.master}")
private String master;
//JedisPoolConfig配置连接池,配置空闲数和连接数,info clients 查看连接数,client list 查看详情
@Bean
public JedisPoolConfig getRedisConfig(){
JedisPoolConfig jpc=new JedisPoolConfig();
jpc.setMaxIdle(10);//最大空闲
jpc.setMaxTotal(30);//最大连接
return jpc;
}
//RedisSentinelConfiguration配置哨兵模式,配置哨兵ip和端口,master主机
@Bean
public RedisSentinelConfiguration sentinelConfiguration(){
RedisSentinelConfiguration redisSentinelConfiguration = new RedisSentinelConfiguration();
//配置matser的名称
redisSentinelConfiguration.master(master);
//配置redis的哨兵sentinel
Set redisNodeSet = new HashSet<>();
nodes.forEach(x->{
redisNodeSet.add(new RedisNode(x.split(":")[0],Integer.parseInt(x.split(":")[1])));
});
logger.info("redisNodeSet -->"+redisNodeSet);
redisSentinelConfiguration.setSentinels(redisNodeSet);
return redisSentinelConfiguration;
}
//JedisConnectionFactory配置连接工厂
@Bean
public JedisConnectionFactory jedisConnectionFactory(JedisPoolConfig jedisPoolConfig,RedisSentinelConfiguration sentinelConfig) {
JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(sentinelConfig,jedisPoolConfig);
return jedisConnectionFactory;
}
@Bean
public RedisTemplate redisTemplate(JedisConnectionFactory jedisConnectionFactory) {
RedisTemplate redisTemplate = new RedisTemplate();
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setConnectionFactory(jedisConnectionFactory);
return redisTemplate;
}
}
RedisTemplate用于处理复杂数据类型,比如对象,集合。默认采用是jdk序列化策略。
StringRedisTemplate用于处理字符串类型,默认采用的是String序列化策略
RedisTemplate用于处理复杂数据类型时需要配置序列化,否则运行时报错
参考文章:https://blog.csdn.net/yifanSJ/article/details/79513179
调用:
@RestController
@RequestMapping("user")
public class LoginController {
@Autowired
private RedisTemplate redisTemplate;
@PostMapping("/login")
public String login(String password,String username){
ValueOperations valueOperations = redisTemplate.opsForValue();
valueOperations.set("ycx","aaa");
}
}
在这里添加了一个数据,去redis中查看,发现都存在。
断掉主服务器,过段时间再执行去添加其他内容,发现存在,集成完毕。