首页 > 其他分享 >【SpringBoot】Jedis和Lettuce的区别

【SpringBoot】Jedis和Lettuce的区别

时间:2024-11-01 12:46:38浏览次数:3  
标签:SpringBoot redis springframework Lettuce Jedis import org new public

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 JedisConnectionFactoryJedisPoolRedisTemplate需要用到也可以配置一下

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

# redis集群的节点信息

redis.cluster.nodes=192.168.1.3:6379,192.168.1.4:6379,192.168.1.5:6379

# redis连接池的配置

redis.cluster.pool.max-active=8

redis.cluster.pool.max-idle=5

redis.cluster.pool.min-idle=3

 创建配置类

下面是示例代码:

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

package cn.ganlixin.ssm.config;

import org.apache.commons.collections4.CollectionUtils;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import redis.clients.jedis.HostAndPort;

import redis.clients.jedis.JedisCluster;

import redis.clients.jedis.JedisPoolConfig;

import java.util.Set;

import java.util.stream.Collectors;

@Configuration

public class RedisClusterConfig {

    private static final Logger log = LoggerFactory.getLogger(RedisClusterConfig.class);

    @Value("${redis.cluster.nodes}")

    private Set<String> redisNodes;

    @Value("${redis.cluster.pool.max-active}")

    private int maxTotal;

    @Value("${redis.cluster.pool.max-idle}")

    private int maxIdle;

    @Value("${redis.cluster.pool.min-idle}")

    private int minIdle;

    // 初始化redis配置

    @Bean

    public JedisCluster redisCluster() {

        if (CollectionUtils.isEmpty(redisNodes)) {

            throw new RuntimeException();

        }

        // 设置redis集群的节点信息

        Set<HostAndPort> nodes = redisNodes.stream().map(node -> {

            String[] nodeInfo = node.split(":");

            if (nodeInfo.length == 2) {

                return new HostAndPort(nodeInfo[0], Integer.parseInt(nodeInfo[1]));

            else {

                return new HostAndPort(nodeInfo[0], 6379);

            }

        }).collect(Collectors.toSet());

        // 配置连接池

        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();

        jedisPoolConfig.setMaxTotal(maxTotal);

        jedisPoolConfig.setMaxIdle(maxIdle);

        jedisPoolConfig.setMinIdle(minIdle);

        // 创建jediscluster,传入节点列表和连接池配置

        JedisCluster cluster = new JedisCluster(nodes, jedisPoolConfig);

        log.info("finish jedis cluster initailization");

        return cluster;

    }

}

测试使用

使用的时候,只需要注入redisCluster即可。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

package cn.ganlixin.ssm.controller;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import redis.clients.jedis.JedisCluster;

import javax.annotation.Resource;

@RestController

@RequestMapping("redis")

public class RedisController {

    @Resource

    private JedisCluster redisCluster;

    @RequestMapping("test")

    public String test() {

        redisCluster.set("hello""world");

        String val = redisCluster.get("hello");

        return val;

    }

}

  

Jedis和Lettuce的区别

Jedis 和 Lettuce 都是用于 Java 语言连接 Redis 的客户端,Jedis主要是同步方法,Lettuce主要是异步高性能,基于Netty。

目前来看,比较好用就是,jedis,lettuce和Redisson这三个客户端

它们分别由不同的团队开发,有一些区别:

设计和实现:

  1. Jedis: Jedis是一个传统的Redis客户端,它使用阻塞I/O,即每个操作都会阻塞线程,直到操作完成或超时。Jedis的设计是单线程的,因此在高并发环境中可能存在性能瓶颈。
  2. Lettuce: Lettuce是基于Netty的异步、非阻塞Redis客户端。它采用了Reactive编程模型,可以更好地处理并发请求,提高性能。

连接管理:

  1. Jedis: Jedis使用连接池来管理与Redis服务器的连接。连接池的使用在高并发环境下可以提高性能。
  2. Lettuce: Lettuce也提供连接池,但与Jedis不同,它使用了更为灵活的连接模型,支持更多的高级特性,如多节点集群、哨兵模式等。

线程安全性:

  1. Jedis: Jedis的实例不是线程安全的,因此在多线程环境中需要使用连接池或者同步来确保线程安全。
  2. Lettuce: Lettuce的实例是线程安全的,可以在多个线程中共享一个实例。

性能:

  1. Jedis: 由于采用阻塞I/O和单线程设计,Jedis在处理大量并发请求时可能性能较低。
  2. Lettuce: 采用了异步、非阻塞的设计,可以更好地处理并发请求,提高性能。

依赖:

  1. Jedis: Jedis主要依赖于Jedis本身。
  2. 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

相关文章

  • SpringBoot抗疫物资调配系统开发
    第1章概述1.1研究背景随着现代网络技术发展,对于抗疫物资管理系统现在正处于网络发展的阶段,所以对它的要求也是比较严格的,要从这个系统的功能和用户实际需求来进行对系统制定开发的发展方式,依靠网络技术的的快速发展和现代通讯技术的结合为用户带来方便,可以方便管理员网......
  • 基于SpringBoot的抗疫物资智能管理平台
    第1章概述1.1研究背景随着现代网络技术发展,对于抗疫物资管理系统现在正处于网络发展的阶段,所以对它的要求也是比较严格的,要从这个系统的功能和用户实际需求来进行对系统制定开发的发展方式,依靠网络技术的的快速发展和现代通讯技术的结合为用户带来方便,可以方便管理员网......
  • SpringBoot项目集成MinIO
    一、MinIO的下载安装以及基本使用1.下载地址:https://dl.min.io/server/minio/release/windows-amd64/minio.exe2.下载好后需要手动创建data文件夹用于存储MinIO中的数据 3.键入cmd 4.设置MinIO的一些变量(第一次启动需要配置)setMINIO_ROOT_USER=adminsetMINIO_ROOT_P......
  • Springboot计算机毕业设计高速公路联网收费系统13z1s
    Springboot计算机毕业设计高速公路联网收费系统本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表项目功能:用户,业务员,收费路段,收费类型,缴费信息开题报告内容一、项目背景随着高速公路网络的不断扩展和交......
  • Springboot计算机毕业设计高校仪器管理系统zr0a9
    Springboot计算机毕业设计高校仪器管理系统zr0a9本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表项目功能:用户,仪器类型,仪器信息,仪器借用,仪器归还,学院,仪器报修,仪器维修,仪器报废开题报告内容一、选题......
  • Springboot计算机毕业设计工业大学医务室管理系统n2t8c
    Springboot计算机毕业设计工业大学医务室管理系统本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表项目功能:学生,教师,科室名称,医生,预约信息,取消预约,开药信息,缴费信息,药品信息,药品入库,药品出库,出诊......
  • 基于SpringBoot的网上书店系统
    引言  随着电子商务的兴起,网上书店逐渐成为消费者购书的重要渠道。相比于传统书店,网上书店具有丰富的图书资源、便捷的购买流程以及多样化的支付方式,极大地提升了用户体验。本文探讨了如何利用SpringBoot+Vue+MySQL+MyBatis技术栈,构建一个基于前后端分离的网上书店......
  • 基于Java+SpringBoot+Vue+HTML5同城上门喂遛宠物系统(源码+LW+调试文档+讲解等)/同城
    博主介绍......
  • 基于Java+SpringBoot+Vue+HTML5中山社区医疗综合服务平台(源码+LW+调试文档+讲解等)/
    博主介绍......
  • 基于Java+SpringBoot+Vue+HTML5库存管理系统(源码+LW+调试文档+讲解等)/库存管理/库存
    博主介绍......