Springboot整合Lettuce
springboot 2.0版本后,spring-boot-starter-data-redis 提供了Lettuce代替Jedis。
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
默认的序列化
默认的序列化,要实现Serializable接口,否则会程序在存储和读取时候会报错。
@Component
@AllArgsConstructor
@NoArgsConstructor
@Data
public class People implements Serializable {
private String name;
private Integer age;
}
我们可能会使用 json 序列化或者其他序列化方式,所以自定义配置类来设置序列化方式。
从 RedisAutoConfiguration 源码中可以看到,自定义了 redisTemplate ,源码中的bean将失效。
可以序列化的key和value很多
自定义序列化
@Configuration
public class RedisConfig {
//自定义redisTemplate
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
// 使用StringRedisSerializer来序列化和反序列化
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// 使用Jackson2JsonRedisSerializer来序列化和反序列化
Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
// 设置对象映射器的可见性,使所有属性都可以被序列化和反序列化
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 启用默认类型信息,以便在序列化和反序列化时处理多态情况
objectMapper.activateDefaultTyping(
objectMapper.getPolymorphicTypeValidator(), //使用getPolymorphicTypeValidator获取多态类型验证器
ObjectMapper.DefaultTyping.NON_FINAL, //设置默认类型检测策略为NON_FINAL,即对非最终类进行类型检测
JsonTypeInfo.As.PROPERTY //设置类型信息存储方式为PROPERTY,即将类型信息作为属性存储在JSON中
);
serializer.setObjectMapper(objectMapper);
// 配置key和value的序列化模式
template.setKeySerializer(stringRedisSerializer);
template.setValueSerializer(serializer);
// 配置hash key和hash value的序列化模式
template.setHashKeySerializer(stringRedisSerializer);
template.setHashValueSerializer(serializer);
template.afterPropertiesSet();
return template;
}
}
执行效果
订阅发布者模式
package com.fs.api.custom.config;
import com.fs.api.custom.subscriber.Receiver;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.io.Serializable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CountDownLatch;
@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisConfig {
private static final Logger logger = LoggerFactory.getLogger(RedisConfig.class);
public static final String SET_TOPIC = "SYSTEM_SETING";
@Autowired
protected ApplicationContext ctx;
@Bean("consumerService")
public ConcurrentMap<String, DefaultMQPushConsumer> consumerService() {
ConcurrentMap<String, DefaultMQPushConsumer> maps = new ConcurrentHashMap();
return maps;
}
@Bean
public RedisTemplate<String, Serializable> redisTemplate(LettuceConnectionFactory connectionFactory) {
RedisTemplate<String, Serializable> template = new RedisTemplate<>();
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
template.setConnectionFactory(connectionFactory);
return template;
}
@Bean
public RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory, MessageListenerAdapter listenerAdapter){
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.addMessageListener(listenerAdapter,new PatternTopic(SET_TOPIC));
return container;
}
@Bean
public MessageListenerAdapter listenerAdapter(Receiver receiver){
return new MessageListenerAdapter(receiver,"receiveMessage");
}
@Bean
public Receiver receiver(CountDownLatch latch){
return new Receiver(latch);
}
}
Springboot整合Jedis
主要依赖:
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
使用Jedis,在SpringBoot2.0以后需要排除lettuce的依赖包,springboot 2.0版本后,spring-boot-starter-data-redis 提供了Lettuce代替Jedis。
<!--在springboot 2.0版本后,spring-boot-starter-data-redis 提供了Lettuce代替Jedis.-->
<!--如果要使用Jedis, 就要在pom.xml中去掉Lettuce 并且添加 Jedis.-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
配置文件
spring:
redis:
port: 6379
host: 127.0.0.1
password:
timeout: 3000
database: 1
jedis:
pool:
max-idle: 8
max-active: 8
min-idle: 2
新增Redis配置,配置RedisConnectionFactory
为JedisConnectionFactory
,JedisPool
,RedisTemplate
需要用到也可以配置一下
package com.example.jedis.configuration;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnection;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
@Configuration
@ConditionalOnClass({GenericObjectPool.class, JedisConnection.class, Jedis.class})
@EnableRedisRepositories(basePackages = "com.example.jedis.repository")
@Slf4j
public class RedisConfiguration {
@Value("${spring.redis.host:127.0.0.1}")
private String host;
@Value("${spring.redis.port:6379}")
private Integer port;
@Value("${spring.redis.password:}")
private String password;
@Value("${spring.redis.database:0}")
private Integer database;
@Value("${spring.redis.jedis.pool.max-active:8}")
private Integer maxActive;
@Value("${spring.redis.jedis.pool.max-idle:8}")
private Integer maxIdle;
@Value("${spring.redis.jedis.pool.max-wait:-1}")
private Long maxWait;
@Value("${spring.redis.jedis.pool.min-idle:0}")
private Integer minIdle;
@Bean
public JedisPoolConfig jedisPoolConfig() {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxIdle(maxIdle);
jedisPoolConfig.setMaxWaitMillis(maxWait);
jedisPoolConfig.setMaxTotal(maxActive);
jedisPoolConfig.setMinIdle(minIdle);
return jedisPoolConfig;
}
@Bean
public RedisStandaloneConfiguration jedisConfig() {
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
config.setHostName(host);
config.setPort(port);
config.setDatabase(database);
config.setPassword(RedisPassword.of(password));
return config;
}
@Bean
public JedisPool jedisPool() {
return new JedisPool(jedisPoolConfig());
}
@Bean
public RedisConnectionFactory jedisConnectionFactory() {
JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(jedisConfig());
jedisConnectionFactory.setPoolConfig(jedisPoolConfig());
return jedisConnectionFactory;
}
@Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(jedisConnectionFactory());
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
return template;
}
}
或者
@Configuration
public class RedisConfig {
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.password}")
private String password;
@Bean
public JedisConnectionFactory jedisConnectionFactory() {
RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();
configuration.setHostName(host);
configuration.setPort(port);
configuration.setPassword(password);
JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(configuration);
return jedisConnectionFactory;
}
@Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(jedisConnectionFactory());
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
return redisTemplate;
}
}
使用RedisTemplate操作Redis:在需要使用Redis的地方,通过@Autowired注入RedisTemplate,并使用其提供的方法来操作Redis。
@Service
public class RedisService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
public void set(String key, Object value) {
redisTemplate.opsForValue().set(key, value);
}
public Object get(String key) {
return redisTemplate.opsForValue().get(key);
}
public void delete(String key) {
redisTemplate.delete(key);
}
}
集群
在配置文件中加入一下内容:
1 2 3 4 5 6 |
|
创建配置类
下面是示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
|
测试使用
使用的时候,只需要注入redisCluster即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
Jedis和Lettuce的区别
Jedis 和 Lettuce 都是用于 Java 语言连接 Redis 的客户端,Jedis主要是同步方法,Lettuce主要是异步高性能,基于Netty。
目前来看,比较好用就是,jedis,lettuce和Redisson这三个客户端
它们分别由不同的团队开发,有一些区别:
设计和实现:
- Jedis: Jedis是一个传统的Redis客户端,它使用阻塞I/O,即每个操作都会阻塞线程,直到操作完成或超时。Jedis的设计是单线程的,因此在高并发环境中可能存在性能瓶颈。
- Lettuce: Lettuce是基于Netty的异步、非阻塞Redis客户端。它采用了Reactive编程模型,可以更好地处理并发请求,提高性能。
连接管理:
- Jedis: Jedis使用连接池来管理与Redis服务器的连接。连接池的使用在高并发环境下可以提高性能。
- Lettuce: Lettuce也提供连接池,但与Jedis不同,它使用了更为灵活的连接模型,支持更多的高级特性,如多节点集群、哨兵模式等。
线程安全性:
- Jedis: Jedis的实例不是线程安全的,因此在多线程环境中需要使用连接池或者同步来确保线程安全。
- Lettuce: Lettuce的实例是线程安全的,可以在多个线程中共享一个实例。
性能:
- Jedis: 由于采用阻塞I/O和单线程设计,Jedis在处理大量并发请求时可能性能较低。
- Lettuce: 采用了异步、非阻塞的设计,可以更好地处理并发请求,提高性能。
依赖:
- Jedis: Jedis主要依赖于Jedis本身。
- Lettuce: Lettuce依赖于Netty,这使得它更灵活和可扩展。
总体而言,选择使用Jedis还是Lettuce取决于具体的使用场景和需求。如果在高并发环境中,并希望利用异步和反应式编程的优势,Lettuce可能是更好的选择。如果对性能要求不是很高,并且喜欢简单的同步模型,Jedis也是一个可行的选择。选择其中一个取决于项目的具体需求和性能要求。
标签:SpringBoot,redis,springframework,Lettuce,Jedis,import,org,new,public From: https://blog.csdn.net/zhyooo123/article/details/143425586