Lettuce 和 Jedis 的定位都是Redis的client
Jedis在实现上是直接连接的redis server,如果在多线程环境下是非线程安全的,这个时候只有使用连接池,为每个Jedis实例增加物理连接
Lettuce的连接是基于Netty的,连接实例(StatefulRedisConnection)可以在多个线程间并发访问,因为StatefulRedisConnection是线程安全的,所以一个连接实例(StatefulRedisConnection)就可以满足多线程环境下的并发访问,当然这个也是可伸缩的设计,一个连接实例不够的情况也可以按需增加连接实例。
springboot2之前redis的连接池为jedis,2.0以后redis的连接池改为了lettuce,lettuce能够支持redis4,需要java8及以上。lettuce是基于netty实现的与redis进行同步和异步的通信,之前看到spring-session-data-redis里的samples已经改为使用LettuceConnectionFactory
所以下面我们看下如何来使用Lettuce来操作Redis
简单介绍下spring-boot-starter-data-redis, 通过看RedisAutoConfiguration的源码
@Import({LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class})
可以知道RedisAutoConfiguration完成了对JedisConnectionFactory和LettuceConnectionFactory的自动配置。
同时RedisProperties源码中封装了对redis配置,包括jedis和lettuce
@ConfigurationProperties(
prefix = "spring.redis"
)
private final RedisProperties.Jedis jedis = new RedisProperties.Jedis();
private final RedisProperties.Lettuce lettuce = new RedisProperties.Lettuce();
因此我们在使用时直接通过yml配置即可使用Lettuce来连接Redis,下面我们来看具体使用
maven项目,引入依赖,注意lettuce连接池的使用需要引入commons-pool2依赖包
org.springframework.boot
spring-boot-starter-data-redis
org.apache.commons
commons-pool2
yml配置
spring:
redis:
host: ip
port: port
password: password
timeout: 2000
lettuce:
pool:
max-active: 8
max-wait: 1
max-idle: 8
min-idle: 0
封装Redis常用方法工具类
注意:
这些都可以根据自己需要去实现,我们主要来展示操作redis的接口
/**
* @filename RedisService
*
*
@description 封装Redis常用方法
*
* @author llspace
* @version 1.0
* @since 2019/6/27 11:13
**/
@Component
public class RedisService {
@Autowired
private StringRedisTemplate redisTemplate;
/**
* set方法
*/
public boolean set(RedisKeyPrefix prefix, String key, T value){
boolean flag = false;
try{
ValueOperations operations = redisTemplate.opsForValue();
String realKey = prefix.realKey(key);
operations.set(realKey, JsonUtil.toJSONString(value));
//expire <= 0 表示无限期, 不设置
if(prefix.expire() > 0){
redisTemplate.expire(realKey, prefix.expire(), TimeUnit.SECONDS);
}
flag = true;
} catch (Exception e){
e.printStackTrace();
}
return flag;
}
/**
* 判断key是否存在
*/
public boolean exists(RedisKeyPrefix prefix, String key){
return redisTemplate.hasKey(prefix.realKey(key));
}
/**
* 删除
*/
public void delete(RedisKeyPrefix prefix, String key){
if(exists(prefix, key)){
redisTemplate.delete(prefix.realKey(key));
}
}
/**
* 按规则批量删除
*/
public void deletePattern(String pattern){
Set keys = redisTemplate.keys(pattern);
if(keys != null && keys.size() > 0){
redisTemplate.delete(keys);
}
}
/**
* get方法,获取javabean
*/
public T getBean(RedisKeyPrefix prefix, String key, Class clazz){
ValueOperations operations = redisTemplate.opsForValue();
String value = operations.get(prefix.realKey(key));
return JsonUtil.toBean(value, clazz);
}
/**
* get方法,获取java list
*/
public List getList(RedisKeyPrefix prefix, String key, Class clazz){
ValueOperations operations = redisTemplate.opsForValue();
String value = operations.get(prefix.realKey(key));
return JsonUtil.toList(value, clazz);
}
public Long incr(RedisKeyPrefix prefix, String key){
ValueOperations operations = redisTemplate.opsForValue();
return operations.increment(prefix.realKey(key));
}
public Long decr(RedisKeyPrefix prefix, String key){
ValueOperations operations = redisTemplate.opsForValue();
return operations.decrement(prefix.realKey(key));
}
}
参考RedisAutoConfiguration源码
@Configuration
@ConditionalOnClass({RedisOperations.class})
@EnableConfigurationProperties({RedisProperties.class})
@Import({LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class})
public class RedisAutoConfiguration {
public RedisAutoConfiguration() {
}
@Bean
@ConditionalOnMissingBean(
name = {"redisTemplate"}
)
public RedisTemplate
下面我们来自定义我们的RedisConfig(key为 String类型, value为 Object类型)
/**
* @filename RedisConfig
*
*
@description Redis配置类
*
* @author llspace
* @version 1.0
* @since 2019/6/27 13:33
**/
@Configuration
public class RedisConfig {
/**
* RedisTemplate配置
*/
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
RedisTemplate template = new RedisTemplate();
template.setConnectionFactory(factory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
具体实现的RedisSerializer还有很多,根据自己的需求选择配置即可,比如fastjson也有FastJsonRedisSerializer和GenericFastJsonRedisSerializer的实现