背景介绍
由于很多人推荐使用RedisTemplate来操作redis,而且springboot至2.2版本开始就已经使用lettuce了,所以换成了lettuce+RedisTemplate
lettuce与jedis链接池对比
Lettuce 和 Jedis 的定位都是Redis的client,所以他们当然可以直接连接redis server。
spring boot框架中已经集成了redis,在1.x.x的版本时默认使用的jedis客户端,现在是2.x.x版本默认使用的lettuce客户端。
Jedis
Jedis在实现上是直接连接的redis server,如果在多线程环境下是非线程安全的,这个时候只有使用连接池,为每个Jedis实例增加物理连接
Lettuce
Lettuce的连接是基于Netty的,连接实例(StatefulRedisConnection)可以在多个线程间并发访问,应为StatefulRedisConnection是线程安全的,所以一个连接实例(StatefulRedisConnection)就可以满足多线程环境下的并发访问,当然这个也是可伸缩的设计,一个连接实例不够的情况也可以按需增加连接实例。
lettuce主要利用netty实现与redis的同步和异步通信。
一、pom引用
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
二、yml配置
spring:
application:
name: ${parm.service.name}
#redis单机版
redis:
host: ${parm.redis.host-name}
port: ${parm.redis.port}
# 密码 没有则可以不填
password: ${parm.redis.password}
database: ${parm.redis.db1}
timeout: 2000
# 如果使用的jedis 则将lettuce改成jedis即可
lettuce:
pool:
max-total: 12
# 最大活跃链接数 默认8(使用负值表示没有限制)
max-active: 12
# 最大空闲连接数 默认8
max-idle: 12
# 最小空闲连接数 默认0
min-idle: 0
# 连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1
config配置
@Configuration
public class LettuceRedisConfig {
@Autowired
private Environment environment;
/**
* 获取连接池信息
*
* @return
* @Scope(value = "prototype")代表原型模式
* @Scope(value = "singleton")代表单例模式
* Spring定义了多种作用域,可以基于这些作用域创建bean,包括:
* 单例( Singleton):在整个应用中,只创建bean的一个实例。
* 原型( Prototype):每次注入或者通过Spring应用上下文获取的时候,都会创建一个新的bean实例。
* 会话( Session):在Web应用中,为每个会话创建一个bean实例。
* 请求( Rquest):在Web应用中,为每个请求创建一个bean实例。
*/
@Bean
@ConfigurationProperties(prefix = "spring.redis.lettuce.pool")
@Scope(value = "prototype")
public GenericObjectPoolConfig redisPool() {
return new GenericObjectPoolConfig();
}
/**
* 获取redis连接池信息
*
* @return
*/
@Bean
@ConfigurationProperties(prefix = "parm.redis")
public RedisStandaloneConfiguration redisConfigA() {
return new RedisStandaloneConfiguration();
}
@Primary
@Bean("redisTemplate1")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = getRedisTemplate(redisConnectionFactory);
return redisTemplate;
}
@Bean("redisTemplate2")
public RedisTemplate<String, Object> redisTemplate2(GenericObjectPoolConfig redisPool, RedisStandaloneConfiguration redisConfigA,
@Value("${parm.redis.db2}") int database2) {
redisConfigA.setDatabase(database2);
LettucePoolingClientConfiguration.LettucePoolingClientConfigurationBuilder builder = LettucePoolingClientConfiguration.builder();
builder.poolConfig(redisPool);
LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(redisConfigA, builder.build());
connectionFactory.afterPropertiesSet();
return getRedisTemplate(connectionFactory);
}
public RedisTemplate getRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
RedisSerializer<String> stringSerializer = new StringRedisSerializer();
redisTemplate.setKeySerializer(stringSerializer);
redisTemplate.setHashKeySerializer(stringSerializer);
//设置序列化接口
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
mapper.setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.NONE);
mapper.setVisibility(PropertyAccessor.IS_GETTER, JsonAutoDetect.Visibility.NONE);
SimpleFilterProvider filterProvider = new SimpleFilterProvider();
filterProvider.setDefaultFilter(SimpleBeanPropertyFilter.serializeAll());
mapper.setFilterProvider(filterProvider);
GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer(mapper);
// key序列化
redisTemplate.setKeySerializer(stringSerializer);
// value序列化
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
// Hash key序列化
redisTemplate.setHashKeySerializer(stringSerializer);
// Hash value序列化
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
引用
@Autowired
@Qualifier("redisTemplate1")
private RedisTemplate<String, Object> redisTemplate;
#redisTemplate里有各种redis类型的操作通过 opsFor**()方法来操作具体需要
redisTemplate.opsForHash().put("OTT_" + code + "_" + hashKey, key, value);
获取所有的key
keys方法比较耗费性能,不推荐使用 public static List<String> getkeys(RedisTemplate redisTemplate) {
List<String> result = new ArrayList<>();
try {
String patternKey = "*";
ScanOptions options = ScanOptions.scanOptions()
//这里指定每次扫描key的数量(很多博客瞎说要指定Integer.MAX_VALUE,这样的话跟 keys有什么区别?)
.count(20)
.match(patternKey).build();
RedisSerializer<String> redisSerializer = (RedisSerializer<String>) redisTemplate.getKeySerializer();
Cursor cursor = (Cursor) redisTemplate.executeWithStickyConnection(redisConnection -> new ConvertingCursor<>(redisConnection.scan(options), redisSerializer::deserialize));
while (cursor.hasNext()) {
result.add(cursor.next().toString());
}
//切记这里一定要关闭,否则会耗尽连接数。报Cannot get Jedis connection; nested exception is redis.clients.jedis.exceptions.JedisException: Could not get a
cursor.close();
} catch (IOException e) {
return null;
}
return result;
}
问题解决
1、问题一、链接超时
io.lettuce.core.RedisCommandTimeoutException: Command timed out
原因具体没有调查清除,有的说是springboot中配置的timeout时间过短,导致的 但是我设置了5s过段时间不连接还是超时,后来修改redis中的配置文件,把tcp-keepalive设置成0-20之间。timeout设置为0 然后重启了redis。然后到现在没有发现有问题 。先观察一段时间。
2、问题二、无法连接
io.lettuce.core.RedisConnectionException: Unable to connect to 192.168.43.129:6379
通常是参数比如ip、端口、密码等不正确
本文介绍如何在Spring Boot项目中使用Lettuce和RedisTemplate进行Redis操作,并对比了Lettuce与Jedis的不同之处。同时提供了详细的配置示例及常见问题解决方案。
1022

被折叠的 条评论
为什么被折叠?



