本文側重於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<String> 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集成。
springboot集成
pom依賴:
<!--jedis-->
<!-- <dependency>-->
<!-- <groupId>redis.clients</groupId>-->
<!-- <artifactId>jedis</artifactId>-->
<!-- <version>2.9.0</version>-->
<!-- </dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
兩者不兼容或版本號不兼容
同時引入有可能會導致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<String> 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<RedisNode> 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<String, Object> redisTemplate(JedisConnectionFactory jedisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
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<String, String> valueOperations = redisTemplate.opsForValue();
valueOperations.set("ycx","aaa");
}
}
在這裏添加了一個數據,去redis中查看,發現都存在。
斷掉主服務器,過段時間再執行去添加其他內容,發現存在,集成完畢。