上周在自己的项目中发现了一个问题,由于用户信息是在redis中缓存的,所以登录和聊天都需要从redis中获取到对应的用户信息。但是发现刚启动或者几分钟未访问后首次访问,都会报一个command timed out异常,然在后台能看到redis重新连接的日志,再进行访问就又正常了。通过baidu得到的结果,要么是把timeout设置成5000,要么是在抛异常的时候捕获到然后重新请求,但是经过我的验证都是无效的。

       最终,我找到了适合自己的解决方法,分享给大家,希望能对大家有所帮助。

1、yml文件配置

spring:
  redis:
    jedis:
      pool:
        # 连接池中的最小空闲连接
        min-idle: 0
        # 连接池中的最大空闲连接
        max-idle: 10
        # 连接池最大连接数(使用负值表示没有限制)
        max-active: 10
        # 连接池最大阻塞等待时间(使用负值表示没有限制)
        max-wait: -1
        testOnBorrow: true
        testWhileIdle: true
        minEvictableIdleTimeMills: 60000
        timeBetweenEvictionRunsMillis: 30000
        numTestsPerEvictionRun: -1
    # 连接超时时间(毫秒)
    timeout: 5000

重点应该是testWhileIdle、minEvictableIdleTimeMills、timeBetweenEvictionRunsMillis、numTestsPerEvictionRun这四个属性

2、在RedisConfig中创建两个Bean,jedisPoolConfig和redisConnectionFactory


    @Bean
    public JedisPoolConfig jedisPoolConfig(){
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();

        jedisPoolConfig.setMaxIdle(maxIdle);
        jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
        jedisPoolConfig.setTestWhileIdle(testWhileIdle);
        jedisPoolConfig.setTestOnBorrow(testOnBorrow);
        jedisPoolConfig.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMills);
        jedisPoolConfig.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
        jedisPoolConfig.setNumTestsPerEvictionRun(numTestsPerEvictionRun);
        jedisPoolConfig.setTestOnCreate(true);
        jedisPoolConfig.setTestOnReturn(true);
        return jedisPoolConfig;
    }

    @Bean
    public RedisConnectionFactory redisConnectionFactory(JedisPoolConfig jedisPoolConfig) {
        RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
        //设置redis服务器的host或者ip地址
        redisStandaloneConfiguration.setHostName(host);
        redisStandaloneConfiguration.setPort(port);
        //获得默认的连接池构造
        //这里需要注意的是,edisConnectionFactoryJ对于Standalone模式的没有(RedisStandaloneConfiguration,JedisPoolConfig)的构造函数,对此
        //我们用JedisClientConfiguration接口的builder方法实例化一个构造器,还得类型转换
        JedisClientConfiguration.JedisPoolingClientConfigurationBuilder jpcf = (JedisClientConfiguration.JedisPoolingClientConfigurationBuilder) JedisClientConfiguration.builder();
        //修改我们的连接池配置
        jpcf.poolConfig(jedisPoolConfig);
        //通过构造器来构造jedis客户端配置
        JedisClientConfiguration jedisClientConfiguration = jpcf.build();

        return new JedisConnectionFactory(redisStandaloneConfiguration, jedisClientConfiguration);
    }

3、获取yml文件中定义的属性

 @Value("${spring.redis.host}")
    private String host;

    @Value("${spring.redis.port}")
    private int port;

    @Value("${spring.redis.timeout}")
    private int timeout;

    @Value("${spring.redis.jedis.pool.max-idle}")
    private int maxIdle;

    @Value("${spring.redis.jedis.pool.max-wait}")
    private long maxWaitMillis;

    @Value("${spring.redis.jedis.pool.testOnBorrow}")
    private Boolean testOnBorrow;

    @Value("${spring.redis.jedis.pool.testWhileIdle}")
    private Boolean testWhileIdle;

    @Value("${spring.redis.jedis.pool.minEvictableIdleTimeMills}")
    private int minEvictableIdleTimeMills;

    @Value("${spring.redis.jedis.pool.timeBetweenEvictionRunsMillis}")
    private int timeBetweenEvictionRunsMillis;

    @Value("${spring.redis.jedis.pool.numTestsPerEvictionRun}")
    private int numTestsPerEvictionRun;

4、把factory给redisTemplate使用

    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<Object, Object>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setKeySerializer(new StringRedisSerializer());//key序列化
        redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer(Object.class));  //value序列化
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer(Object.class));
        redisTemplate.setDefaultSerializer(new Jackson2JsonRedisSerializer(Object.class));
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

重点是前两步,后两步安装自己原来的代码改下就好了,希望能对大家有所帮助。

最后修改于 2019-01-01 11:27:33
如果觉得我的文章对你有用,请随意赞赏
扫一扫支付
上一篇