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;
    }

4

5

6

7

8

原文地址:https://www.cnblogs.com/mediocreWorld/p/15145749.html