百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

Redis进阶十一之Jedis和Lettuce比较

mhr18 2024-10-27 10:54 46 浏览 0 评论

前言

对于Java开发者来说,Jedis和Lettuce是两种非常常见的Redis客户端,他们可以帮助开发者更容易地在Java应用中使用Redis。然而,这两种客户端在设计和实现上有着许多不同之处,这就需要深入理解它们的差异,以便根据自己的需求做出合适的选择。

Lettuce 与Jedis 对比

维度/库

Lettuce

Jedis

单线程/多线程

Lettuce是基于Netty的连接实例(StatefulRedisConnection),可以在多个线程间并发访问,应该被用作长期存在的线程安全对象。

Jedis实例不是线程安全的,因此在多线程环境下,你需要每个线程创建一个新的连接实例,或者使用连接池。

阻塞/非阻塞

Lettuce支持异步、反应式、同步和非阻塞操作。

Jedis操作是同步阻塞的,不支持异步和非阻塞操作。

集群支持

Lettuce提供了Redis Cluster的原生支持。

Jedis也支持Redis Cluster,但需要手动处理重定向。

PUB/SUB模型

Lettuce支持发布-订阅模型。

Jedis也支持发布-订阅模型。

二进制协议

Lettuce直接使用Netty来处理命令和结果,可以处理任何Redis协议和命令。

Jedis使用自己的协议处理器,对协议的支持可能不太完整。

项目活跃度

Lettuce是目前最活跃的Redis Java客户端项目,一直在持续更新和添加新特性。

Jedis的活跃度较低,更新和新功能的添加较慢。

连接池

Lettuce的连接实例是线程安全的,大多数情况下,你不需要使用连接池。不过,Lettuce也提供了一个可选的内置连接池。

在多线程环境下,你需要使用Jedis的连接池来管理和复用连接。

依赖

Lettuce依赖于Netty。

Jedis没有外部依赖。

事务

Lettuce支持Redis的事务。

Jedis也支持Redis的事务。

Sentinel

Lettuce提供了对Redis Sentinel的原生支持。

Jedis也支持Redis Sentinel。

使用Docker安装Redis

a123456@luludeMacBook-Pro-2 Dockerfile % docker run --name myReids -it -p 6379:6379 redis:5.0
1:C 22 Mar 2024 12:36:17.213 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
1:C 22 Mar 2024 12:36:17.213 # Redis version=5.0.14, bits=64, commit=00000000, modified=0, pid=1, just started
1:C 22 Mar 2024 12:36:17.213 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
                _._                                                  
           _.-``__ ''-._                                             
      _.-``    `.  `_.  ''-._           Redis 5.0.14 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._                                   
 (    '      ,       .-`  | `,    )     Running in standalone mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
 |    `-._   `._    /     _.-'    |     PID: 1
  `-._    `-._  `-./  _.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |           http://redis.io        
  `-._    `-._`-.__.-'_.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |                                  
  `-._    `-._`-.__.-'_.-'    _.-'                                   
      `-._    `-.__.-'    _.-'                                       
          `-._        _.-'                                           
              `-.__.-'                                               

1:M 22 Mar 2024 12:36:17.218 # Server initialized
1:M 22 Mar 2024 12:36:17.218 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
1:M 22 Mar 2024 12:36:17.218 * Ready to accept connections              

检查Redis是否启动成功

a123456@luludeMacBook-Pro-2 ~ % docker ps
CONTAINER ID   IMAGE       COMMAND                  CREATED          STATUS          PORTS                    NAMES
8a4ea1b7577c   redis:5.0   "docker-entrypoint.s…"   44 seconds ago   Up 43 seconds   0.0.0.0:6379->6379/tcp   myReids
4190cf0b96fe   ubuntu      "/bin/bash"              24 hours ago     Up 24 hours    

进入容器

a123456@luludeMacBook-Pro-2 ~ % docker exec -it myReids redis-cli
127.0.0.1:6379> 

Lettuce介绍

官网地址:Lettuce Reference Guide

Lettuce是基于Netty的,Netty是一个多线程的,事件驱动的I/O框架。这意味着Lettuce可以处理多个并发连接,因此它是线程安全的。例如,如果你有一个应用程序,它在多个线程中并发地访问Redis,你可以创建一个Lettuce连接实例,并且所有的线程都可以使用这个连接实例。这是因为Lettuce内部会处理并发访问,保证数据的一致性。

Lettuce入门

引入依赖:

<dependency>
    <groupId>io.lettuce</groupId>
    <artifactId>lettuce-core</artifactId>
    <version>6.3.2.RELEASE</version>
</dependency>
public class LettuceTest {
    public static void main(String[] args) {
        RedisURI redisURI = RedisURI.Builder.redis("localhost", 6379).build();

        RedisClient redisClient = RedisClient.create(redisURI);
        StatefulRedisConnection<String, String> connection = redisClient.connect();
        RedisCommands<String, String> syncCommands = connection.sync();

        syncCommands.set("lettuce", "Hello, Lettuce!");

        connection.close();
        redisClient.shutdown();
    }
}
a123456@luludeMacBook-Pro-2 ~ % docker exec -it myReids redis-cli
127.0.0.1:6379> get lettuce
"Hello, Lettuce!"
127.0.0.1:6379>

通过 Get 命令查询 lettuce 的值,设置lettuce值成功。

Jedis介绍

请参考:

Redis进阶九之SpringBoot配置多Redis源

Redis进阶十之JedisPool资源池优化

SpringBoot集成Redis (Lettuce)

POM文件

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-parent</artifactId>
        <version>2.3.1.RELEASE</version>
    </parent>

    <groupId>org.example</groupId>
    <artifactId>redistest</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!-- lettuce pool 缓存连接池-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
            <version>2.8.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
        </dependency>
    </dependencies>
</project>

CahceConfig 类

@Configuration
public class CacheConfig {
    @Bean(name = "poolConfig")
    @ConfigurationProperties(prefix = "spring.redis.lettuce.pool")
    public GenericObjectPoolConfig poolConfig() {
        return new GenericObjectPoolConfig();
    }

    /**
     * 配置自定义redisTemplate
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(@Autowired LettuceConnectionFactory lettuceConnectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(lettuceConnectionFactory);
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        // 设置值(value)的序列化采用Jackson2JsonRedisSerializer。
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        // 设置键(key)的序列化采用StringRedisSerializer。
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());

        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    @Bean
    public LettuceConnectionFactory lettuceConnectionFactory(
            @Value("${spring.redis.host}") String host,
            @Value("${spring.redis.port}") int port,
            @Autowired @Qualifier("poolConfig") GenericObjectPoolConfig config) {

        RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
        redisStandaloneConfiguration.setHostName(host);
        redisStandaloneConfiguration.setPort(port);
        LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder()
                .commandTimeout(Duration.ofMillis(2000))
                .shutdownTimeout(Duration.ofMillis(30000))
                .poolConfig(config)
                .build();

        LettuceConnectionFactory factory = new LettuceConnectionFactory(redisStandaloneConfiguration, clientConfig);

        return factory;
    }
}

单元测试

@RunWith(SpringRunner.class)
@SpringBootTest(classes = WebApplication.class)
public class RedisTemplateTest {
    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Test
    public void testRedis() {
        User user = new User(1L, "yangyang", 18);
        String cacheKey = "user:" + user.getId();
        redisTemplate.opsForValue().set(cacheKey, user);
    }
}

访问Redis

127.0.0.1:6379> get user:1
"{\"id\":1,\"name\":\"yangyang\",\"age\":18}"
127.0.0.1:6379> 

相关推荐

如何检查 Linux 服务器是物理服务器还是虚拟服务器?

在企业级运维、故障排查和性能调优过程中,准确了解服务器的运行环境至关重要。无论是物理机还是虚拟机,都存在各自的优势与限制。在很多场景下,尤其是当你继承一台服务器而不清楚底层硬件细节时,如何快速辨识它是...

第四节 Windows 系统 Docker 安装全指南

一、Docker在Windows上的运行原理(一)架构限制说明Docker本质上依赖Linux内核特性(如Namespaces、Cgroups等),因此在Windows系统上无法直...

C++ std:shared_ptr自定义allocator引入内存池

当C++项目里做了大量的动态内存分配与释放,可能会导致内存碎片,使系统性能降低。当动态内存分配的开销变得不容忽视时,一种解决办法是一次从操作系统分配一块大的静态内存作为内存池进行手动管理,堆对象内存分...

Activiti 8.0.0 发布,业务流程管理与工作流系统

Activiti8.0.0现已发布。Activiti是一个业务流程管理(BPM)和工作流系统,适用于开发人员和系统管理员。其核心是超快速、稳定的BPMN2流程引擎。Activiti可以...

MyBatis动态SQL的5种高级玩法,90%的人只用过3种

MyBatis动态SQL在日常开发中频繁使用,但大多数开发者仅掌握基础标签。本文将介绍五种高阶技巧,助你解锁更灵活的SQL控制能力。一、智能修剪(Trim标签)应用场景:动态处理字段更新,替代<...

Springboot数据访问(整合Mybatis Plus)

Springboot整合MybatisPlus1、创建数据表2、引入maven依赖mybatis-plus-boot-starter主要引入这个依赖,其他相关的依赖在这里就不写了。3、项目结构目录h...

盘点金州勇士在奥克兰13年的13大球星 满满的全是...

见证了两个月前勇士与猛龙那个史诗般的系列赛后,甲骨文球馆正式成为了历史。那个大大的红色标志被一个字母一个字母地移除,在周四,一切都成为了过去式。然而这座,别名为“Roaracle”(译注:Roar怒吼...

Mybatis入门看这一篇就够了(mybatis快速入门)

什么是MyBatisMyBatis本是apache的一个开源项目iBatis,2010年这个项目由apachesoftwarefoundation迁移到了googlecode,并且改名为M...

Springboot数据访问(整合druid数据源)

Springboot整合druid数据源基本概念SpringBoot默认的数据源是:2.0之前:org.apache.tomcat.jdbc.pool.DataSource2.0及之后:com.z...

Linux 中的 &quot;/etc/profile.d&quot; 目录有什么作用 ?

什么是/etc/profile.d/目录?/etc/profile.d/目录是Linux系统不可或缺的一部分保留配置脚本。它与/etc/profile文件相关联,这是一个启动脚本,该脚...

企业数据库安全管理规范(企业数据库安全管理规范最新版)

1.目的为规范数据库系统安全使用活动,降低因使用不当而带来的安全风险,保障数据库系统及相关应用系统的安全,特制定本数据库安全管理规范。2.适用范围本规范中所定义的数据管理内容,特指存放在信息系统数据库...

Oracle 伪列!这些隐藏用法你都知道吗?

在Oracle数据库中,有几位特殊的“成员”——伪列,它们虽然不是表中真实存在的物理列,但却能在数据查询、处理过程中发挥出意想不到的强大作用。今天给大家分享Oracle伪列的使用技巧,无论...

Oracle 高效处理数据的隐藏神器:临时表妙用

各位数据库搬砖人,在Oracle的代码世界里闯荡,处理复杂业务时,是不是总被数据“搅得头大”?今天给大家安利一个超实用的隐藏神器——临时表!当你需要临时存储中间计算结果,又不想污染正式数据表...

Oracle 数据库查询:多表查询(oracle多表关联查询)

一、多表查询基础1.JOIN操作-INNERJOIN:返回两个表中满足连接条件的匹配行,不保留未匹配数据。SELECTa.emp_id,b.dept_nameFROMempl...

一文掌握怎么利用Shell+Python实现多数据源的异地备份程序

简介:在信息化时代,数据安全和业务连续性已成为企业和个人用户关注的焦点。无论是网站数据、数据库、日志文件,还是用户上传的文档、图片等,数据一旦丢失,损失难以估量。尤其是当数据分布在多个不同的目录、服务...

取消回复欢迎 发表评论: