springboot整合redis异常汇总

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springboot整合redis异常汇总相关的知识,希望对你有一定的参考价值。

参考技术A

项目中要用到redis,于是尝试通过springboot整合redis,redis集群采用3主3从,搭建方法参考: https://developer.aliyun.com/article/767317

springboot从2.x版本开始默认使用lettuce访问redis,所以部分配置由jedis改为lettuce

异常1: Cannot retrieve initial cluster partitions from initial URIs [RedisURI [host=\'192.168.1.1\', port=6379]]
这个问题绕了很多弯路,根据网上的很多方案,以为是redis集群配置成了主从模式,但是springboot连接使用的是cluster模式,最后发现问题出在spring.redis.timeout=0这条配置上。
spring.redis.timeout,在1.0中,时间相关的配置参数类型为int,默认单位为毫秒, 而且设置为0意味着不超时 ,2.x版本中参数类型为Duration,需要添加单位,如:500ms

异常2: java.lang.NoClassDefFoundError: org/apache/commons/pool2/impl/GenericObjectPoolConfig
添加依赖即可
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.8.0</version>
</dependency>

异常3:Caused by: io.lettuce.core.RedisCommandExecutionException: CLUSTERDOWN The cluster is down
1.如果在配置文件中给redis设置了密码,还需要在redis-cli终端设置一下
config set requirepass xxxx(密码)
2.redis-cli 检查cluster的状态
cluster info
3.配置文件中cluster-require-full-coverage设置为no,重启redis服务,可参考: https://stackoverflow.com/questions/53594257/clusterdown-the-cluster-is-down-in-redis

SpringBoot和Redis整合

一、什么是Redis?

  Redis是一个NoSQL数据库,非关系型数据库,是一个key—value(键值)数据库。 

二、SpringBoot整合Redis的两种方法

1、使用Jedis整合Redis

  Jedis是Redis官网对java操作redis-api的一个封装框架。

 添加jedis依赖

    <dependency>
      <groupId>redis.clients</groupId>
      <artifactId>jedis</artifactId>
    </dependency>

 在application.properties配置文件中添加redis配置

spring.redis.host=47.97.197.62
spring.redis.port=6379
spring.redis.timeout=3
spring.redis.password=123456
spring.redis.pool-max-total=10
spring.redis.pool.max-idle=10
spring.redis.pool.max-wait=3
spring.redis.pool.max-active=8

 添加配置类RedisConfig.java

package com.imooc.miaosha.redis;

import org.apache.ibatis.annotations.Param;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties(prefix ="spring.redis")
public class RedisConfig {
    private String host;
    private int port;
    private int timeout;
    private String password;
    private int poolMaxTotal;
    private int poolMaxIdle;
    private int poolMaxWait;

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public int getTimeout() {
        return timeout;
    }

    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public int getPoolMaxTotal() {
        return poolMaxTotal;
    }

    public void setPoolMaxTotal(int poolMaxTotal) {
        this.poolMaxTotal = poolMaxTotal;
    }

    public int getPoolMaxIdle() {
        return poolMaxIdle;
    }

    public void setPoolMaxIdle(int poolMaxIdle) {
        this.poolMaxIdle = poolMaxIdle;
    }

    public int getPoolMaxWait() {
        return poolMaxWait;
    }

    public void setPoolMaxWait(int poolMaxWait) {
        this.poolMaxWait = poolMaxWait;
    }
}

 RedisPoolFactory.java

package com.imooc.miaosha.redis;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

@Service
public class RedisPoolFactory {

    @Autowired
    RedisConfig redisConfig;

    @Bean
    public JedisPool JedisPoolFactory(){
        JedisPoolConfig poolConfig=new JedisPoolConfig();
        poolConfig.setMaxIdle(redisConfig.getPoolMaxIdle());
        poolConfig.setMaxTotal(redisConfig.getPoolMaxTotal());
        poolConfig.setMaxWaitMillis(redisConfig.getPoolMaxWait()*1000);
        JedisPool jp=new JedisPool(poolConfig,redisConfig.getHost(),redisConfig.getPort(),redisConfig.getTimeout()*1000,redisConfig.getPassword(),0);
        return jp;

    }
}

 RedisService.java

package com.imooc.miaosha.redis;

import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

@Service
public class RedisService {

    @Autowired
    JedisPool jedisPool;

    /**
     * 获取单个对象
     */
    public <T> T get(KeyPrefix prefix,String key, Class<T> clazz) {
        Jedis jedis=null;
        try{
            jedis=jedisPool.getResource();
            //生成真正的key
            String realKey=prefix.getPrefix()+key;
            String str= jedis.get(realKey);
            T t=stringToBean(str,clazz);
            return t;
        }finally {
            returnToPool(jedis);
        }
    }

    /**
     * 设置对象
     */
    public <T>boolean set(KeyPrefix prefix, String key, T value) {
        Jedis jedis=null;
        try{
            jedis=jedisPool.getResource();
            String str= beanToString(value);
            if(str==null||str.length()<=0){
                return false;

            }
            //生成真正的key
            String realKey=prefix.getPrefix()+key;
            int seconds= prefix.expireSeconds();
            if(seconds<=0){
                jedis.set(realKey,str);
            }else {
                jedis.setex(realKey,seconds,str);
            };
            return true;
        }finally {
            returnToPool(jedis);
        }
    }


    /**
     * 判断key是否存在
     */
    public <T>boolean exists(KeyPrefix prefix, String key) {
        Jedis jedis=null;
        try{
            jedis=jedisPool.getResource();
            //生成真正的key
            String realKey=prefix.getPrefix()+key;
            return jedis.exists(realKey);
        }finally {
            returnToPool(jedis);
        }
    }


    /**
     * 增加值
     */
    public <T>Long incr(KeyPrefix prefix, String key) {
        Jedis jedis=null;
        try{
            jedis=jedisPool.getResource();
            //生成真正的key
            String realKey=prefix.getPrefix()+key;
            return jedis.incr(realKey);
        }finally {
            returnToPool(jedis);
        }
    }

    /**
     * 减少值
     */
    public <T> Long decr(KeyPrefix prefix, String key) {
        Jedis jedis=null;
        try{
            jedis=jedisPool.getResource();
            //生成真正的key
            String realKey=prefix.getPrefix()+key;
            return jedis.decr(realKey);
        }finally {
            returnToPool(jedis);
        }
    }
    
    private <T> String beanToString(T value){

        if(value==null){
            return null;
        }
        Class<?> clazz=value.getClass();
        if(clazz==int.class||clazz==Integer.class){
            return ""+value;
        }else if(clazz==String.class){
            return(String)value;
        }else if(clazz==long.class||clazz==Long.class){
            return ""+value;
        }else {
            return JSON.toJSONString(value);
        }
    }

    @SuppressWarnings("unchecked")
    private <T> T stringToBean(String str,Class<T> clazz){
        if(str==null||str.length()<=0||clazz==null){
            return null;
        }
        if(clazz==int.class||clazz==Integer.class){
            return (T)Integer.valueOf(str);
        }else if(clazz==String.class){
            return (T) str;
        }else if(clazz==long.class||clazz==Long.class){
            return (T)Long.valueOf(str);
        }else {
            return JSON.toJavaObject(JSON.parseObject(str), clazz);
        }
    }

    private void returnToPool(Jedis jedis){
        if(jedis!=null){
            jedis.close();
        }
    }

}

 

2、使用RedisTemplate整合Redis

  RedisTemplate是spring框架对jedis和lettuce的封装。让spring框架体系能够更加方便的接入redis的功能。

添加依赖

    <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>

在启动类上加@EnableCaching注解

@SpringBootApplication
@EnableCaching
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

RedisConfig.java配置类

package com.example.demo.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
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.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;

import java.net.UnknownHostException;


@Configuration
public class RedisConfig {

    @Bean
    @ConditionalOnMissingBean(name = "redisTemplate")
    public RedisTemplate<String, Object> redisTemplate(
            RedisConnectionFactory redisConnectionFactory)
            throws UnknownHostException {

        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(redisConnectionFactory);
        template.setKeySerializer(jackson2JsonRedisSerializer);
        template.setValueSerializer(jackson2JsonRedisSerializer);
        template.setHashKeySerializer(jackson2JsonRedisSerializer);
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }

    @Bean
    @ConditionalOnMissingBean(StringRedisTemplate.class)
    public StringRedisTemplate stringRedisTemplate(
            RedisConnectionFactory redisConnectionFactory)
            throws UnknownHostException {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }
}

 

 

 

 

 

 

 

 

 

 

 

    

 

以上是关于springboot整合redis异常汇总的主要内容,如果未能解决你的问题,请参考以下文章

Mysql连接数据库异常汇总必收藏

问题汇总

知识点-Spring Boot 统一异常处理汇总

超清PDF:Java面试题汇总,共41个技术方向!

SpringBoot + JPA问题汇总

springboot整合logback集成elk实现日志的汇总分析统计和检索功能