problems_redis
problems_redis
1 启动哨兵模式报错
desc: 执行启动命令: redis-server sentinel.conf
errorlog:
*** FATAL CONFIG FILE ERROR ***
Reading the configuration file, at line 69
>>> 'sentinel monitor mymaster node1 6379 2'
sentinel directive while not in sentinel mode
RCA:
启动命令写错了
solution:
添加启动参数 --sentinel
正确的启动命令如下: redis-server sentinel.conf --sentinel
或者直接使用这个命令: redis-sentinel sentinel.conf
[推荐]
2 redis存入到系统的key前面莫名多了一些十六进制字符
比如下面这样的:
"\xac\xed\x00\x05t\x00bbiz.order.exchange:biz.order.save.queue:biz.order.save.routingKey:0fb69837020b41a7954821ea22098be7"
RCA1:没有对redis的key进行序列化,在RedisConfig.java中,配置其序列化方式:
package com.orders.config;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* redis配置
*
* @author 张伟
* @version 1.0.0
* @date 2021-11-25
*/
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
@Bean("redisTemplate3")
@SuppressWarnings(value = {"unchecked", "rawtypes"})
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(connectionFactory);
Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
/*ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
serializer.setObjectMapper(mapper);*/
// 使用StringRedisSerializer来序列化和反序列化redis的key值
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
// 使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值
redisTemplate.setValueSerializer(serializer);
redisTemplate.setHashValueSerializer(serializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
然后,发现还是有这个问题,因为我使用RedisCache.java对redisTemplate进行了一层封装:
@Component
public class RedisCache {
@Autowired
public RedisTemplate redisTemplate;
...
}
就是这个封装出问题了,它使用了@Autowired注解,自动注入redisTemplate,但是系统中有多个redisTemplate的bean对象,它注入了原生的那个bean。
SOLUTION: 使用如下的注解@Resource(name = "redisTemplate3"),根据bean的name指定相应的对象。
@Component
public class RedisCache {
@Resource(name = "redisTemplate3")
public RedisTemplate redisTemplate;
...
}
SOLUTION2:在封装RedisTemplate的bean时,除了加@Bean注解之外,再加一个 @Primary,表示注入 RedisTemplate 的 bean时,优先选择这个。(未测试过)
3 封装的redis starter测试启动报错
ERROR1:
org.springframework.data.redis.RedisConnectionFailureException: Cannot get Jedis connection; nested exception is redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
Caused by: redis.clients.jedis.exceptions.JedisDataException: ERR Client sent AUTH, but no password is set
RCA:
在注入RedisConfiguaration时未判断密码是否为空,直接设置密码。此时当redis服务端没有设置密码,则会报错。
SOLUTION:
设置redis密码前进行判断:
@Bean
@ConditionalOnProperty(name = "spring.redis.mode", havingValue = "standalone", matchIfMissing = true)
public RedisStandaloneConfiguration redisStandaloneConfiguration() {
RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
// 设置redis密码前进行判断
if (StringUtils.hasText(password)) {
redisStandaloneConfiguration.setPassword(password);
}
redisStandaloneConfiguration.setDatabase(Integer.parseInt(database));
Assert.notBlank(host);
Assert.isTrue(host.contains(":"));
Assert.isTrue(!host.contains(","));
String[] divides = host.split(":");
redisStandaloneConfiguration.setHostName(divides[0]);
redisStandaloneConfiguration.setPort(Integer.parseInt(divides[1]));
return redisStandaloneConfiguration;
}