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异常汇总的主要内容,如果未能解决你的问题,请参考以下文章