【入门篇】1.5 redis 客户端Jedis和Lettuce对比详解

news2025/1/18 20:23:17

文章目录

  • 0. 前言
  • 1. Lettuce 与Jedis 对比
  • 2.详解
    • 2.1 线程安全
    • 2.2 阻塞/非阻塞
    • 2.3 集群支持
    • 2.4 PUB/SUB模型
    • 2.5 二进制协议
  • 3. 参考资料

在这里插入图片描述

0. 前言

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

在这篇博客中,将详细讲解Jedis和Lettuce这两种Redis客户端的特点和区别。首先,将介绍他们的基本特性,包括线程安全性、连接管理方式、API设计等。然后,将深入比较他们在处理Redis二进制协议时的差异。最后,将通过一些具体的示例,来展示如何在Java应用中使用Jedis和Lettuce。

1. Lettuce 与Jedis 对比

维度/库LettuceJedis
单线程/多线程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的事务。
SentinelLettuce提供了对Redis Sentinel的原生支持。Jedis也支持Redis Sentinel。

2.详解

2.1 线程安全

Lettuce是基于Netty的连接实例(StatefulRedisConnection),可以在多个线程间并发访问,应该被用作长期存在的线程安全对象。 Jedis实例不是线程安全的,因此在多线程环境下,你需要每个线程创建一个新的连接实例,或者使用连接池。 举例说明

Lettuce和Jedis的线程安全性是它们的一个主要区别。

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

例如:

RedisClient redisClient = RedisClient.create("redis://localhost:6379/0");
StatefulRedisConnection<String, String> connection = redisClient.connect();

// 在多个线程中使用同一个连接
new Thread(() -> {
    RedisCommands<String, String> commands = connection.sync();
    commands.set("key", "value");
}).start();

new Thread(() -> {
    RedisCommands<String, String> commands = connection.sync();
    String value = commands.get("key");
}).start();

在这个例子中,在两个线程中使用了同一个Redis连接。

而Jedis不是线程安全的。这意味着,如果你试图在多个线程中并发地使用同一个Jedis实例,可能会导致数据混乱、错误或其他未预期的问题。在多线程环境下,你需要为每个线程创建一个新的Jedis实例,或者使用连接池。

例如:

JedisPool pool = new JedisPool(new JedisPoolConfig(), "localhost");

// 在每个线程中创建一个新的Jedis实例
new Thread(() -> {
    try (Jedis jedis = pool.getResource()) {
        jedis.set("key", "value");
    }
}).start();

new Thread(() -> {
    try (Jedis jedis = pool.getResource()) {
        String value = jedis.get("key");
    }
}).start();

2.2 阻塞/非阻塞

Lettuce和Jedis在阻塞/非阻塞操作方面的差异主要体现在它们支持的操作类型上。

Lettuce支持异步、同步和反应式的操作。这是因为它基于Netty,一个为了网络应用设计的多线程、事件驱动的框架。这也意味着你可以使用Lettuce实现非阻塞的操作。

例如,你可以使用Lettuce实现异步操作:

RedisClient redisClient = RedisClient.create("redis://localhost:6379/0");
StatefulRedisConnection<String, String> connection = redisClient.connect();
RedisAsyncCommands<String, String> asyncCommands = connection.async();

RedisFuture<String> futureValue = asyncCommands.get("key");
futureValue.thenAccept(System.out::println);

在这个例子中,异步地从Redis获取一个值,并且一旦值可用,就打印它(这是一个非阻塞操作)。

然而,Jedis只支持同步阻塞的操作。这意味着,在操作完成之前,线程将被阻塞。Jedis不支持异步和非阻塞操作。

例如,当你使用Jedis进行操作时:

Jedis jedis = new Jedis("localhost", 6379);
String value = jedis.get("key");
System.out.println(value);

在这个例子中,从Redis获取一个值,这是一个阻塞操作,因为在值返回之前,线程将被阻塞。

2.3 集群支持

Lettuce提供了Redis Cluster的原生支持。 Jedis也支持Redis Cluster,但需要手动处理重定向。

Lettuce和Jedis在对Redis Cluster的支持方面也存在一些差异。

Lettuce提供了对Redis Cluster的原生支持。它可以自动处理集群中节点的更改,包括从节点到主节点的故障转移,并且在执行命令时自动处理重定向。这是通过周期性地获取集群的当前状态来实现的。

例如,你可以使用Lettuce连接Redis Cluster并执行操作:

RedisClusterClient clusterClient = RedisClusterClient.create("redis://localhost:7379");
StatefulRedisClusterConnection<String, String> connection = clusterClient.connect();
RedisAdvancedClusterAsyncCommands<String, String> asyncCommands = connection.async();

asyncCommands.set("key", "value");

在这个例子中,连接到Redis Cluster并设置一个键值对,Lettuce会自动处理任何由于节点更改而发生的重定向。

另一方面,Jedis也支持Redis Cluster,但是你需要手动处理重定向。这意味着,如果一个操作被重定向到另一个节点,你需要捕获JedisMovedDataException异常,然后重新在正确的节点上执行操作。

例如:

JedisCluster jedisCluster = new JedisCluster(new HostAndPort("localhost", 7379));

try {
    jedisCluster.set("key", "value");
} catch (JedisMovedDataException e) {
    HostAndPort newHost = e.getTargetNode();
    JedisCluster newJedisCluster = new JedisCluster(newHost);
    newJedisCluster.set("key", "value");
}

在这个例子中,试图在Redis Cluster中设置一个键值对,如果的操作被重定向到另一个节点,需要捕获异常并在新的节点上重新执行操作。

2.4 PUB/SUB模型

Lettuce和Jedis都支持Redis的发布-订阅(Pub/Sub)模型,以下是他们的一些区别:

  1. Thread Safety:Lettuce的连接实例是线程安全的,因此你可以在多个线程中共享同一个连接实例,而不需要担心线程安全问题。而Jedis实例不是线程安全的,所以在实现发布-订阅模型时,你需要为每个线程创建一个新的Jedis实例。

  2. Connection Management:Lettuce使用Netty框架进行网络通信,它可以通过一切异步和同步的通信方式进行连接管理。这意味着在复杂的发布-订阅场景中,Lettuce可能会有更好的性能。而Jedis使用的是Java的标准网络库,它的连接管理是基于阻塞的I/O操作,这会在大量并发操作时影响性能。

  3. API Design:Lettuce的API设计更现代,使用起来可能更加方便。例如,它提供了完全基于Future的异步执行模型,让你能够更好地控制异步操作。而Jedis的API设计比较传统,虽然也支持异步操作,但可能不如Lettuce灵活。

例如,Lettuce的Pub/Sub示例:

RedisClient redisClient = RedisClient.create("redis://localhost:6379");
StatefulRedisPubSubConnection<String, String> pubSubConnection = redisClient.connectPubSub();
pubSubConnection.addListener(new RedisPubSubListener<>(){...});
pubSubConnection.async().subscribe("channel");

Jedis的Pub/Sub示例:

Jedis jedis = new Jedis("localhost");
jedis.subscribe(new JedisPubSub() {...}, "channel");

2.5 二进制协议

Lettuce直接使用Netty来处理命令和结果,可以处理任何Redis协议和命令。 Jedis使用自己的协议处理器,对协议的支持可能不太完整。

二进制协议是在网络中传输数据的一种方式,它将所有数据都转化为二进制格式进行传输。二进制协议相对于文本协议来说,能更有效地利用网络带宽,同时也能更好地保证数据的完整性。

Lettuce是一个基于Netty的Redis客户端,Netty是一个高效的网络框架,支持各种协议,包括TCP/IP,UDP等,也包括二进制协议。Lettuce使用Netty来处理发送到Redis服务器的命令和从Redis服务器接收的结果。因为Netty的协议支持非常完善,所以Lettuce可以处理任何Redis协议和命令,包括二进制协议。

Jedis则使用了自己的协议处理器,虽然它也支持二进制协议,但是由于其处理器的设计可能没有Netty那么全面,对某些协议的支持可能不太完整。

这些差异可能会在一些复杂的使用场景中产生影响。例如,在处理大量数据,或者需要使用特定Redis命令的情况下,Lettuce可能会有更好的表现。然而,在大多数常见的使用场景下,这些差异可能并不明显。

3. 参考资料

Lettuce

  1. 官方文档:Lettuce
  2. GitHub:Lettuce GitHub
  3. 深入了解Lettuce:Understanding Lettuce
  4. Lettuce源码分析:Lettuce source code analysis

Jedis

  1. 官方文档:Jedis
  2. GitHub:Jedis GitHub
  3. 深入了解Jedis:Understanding Jedis
  4. Jedis源码分析:Jedis source code analysis

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1224795.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

重生之我是一名程序员 34

哈喽啊大家晚上好&#xff01; 今天给大家带来的知识是——库函数qsort。首先&#xff0c;给大家介绍一下qsort函数&#xff0c; qsort函数是C标准库中的一种排序函数&#xff0c;用于对数组中的元素进行快速排序。它接受四个参数&#xff1a;待排序数组的基地址&#xff0c;数…

解决:微软在登录时总是弹出需要家长或监护人同意才能使用该账户并且不断循环?

目录 问题来源&#xff1a; 解决办法&#xff1a; 问题来源&#xff1a; 我的edge浏览器账号登录&#xff0c;一直弹出来需要家长或监护人同意才能使用&#xff0c;然后按照提示操作&#xff0c;会一直循环&#xff0c;是个无穷循环。 解决办法&#xff1a; 参考&#xff1…

计算机算法分析与设计(23)---二分搜索算法(C++)

文章目录 1. 算法介绍2. 代码编写 1. 算法介绍 1. 二分搜索&#xff08;英语&#xff1a;binary search&#xff09;&#xff0c;也称折半搜索&#xff08;英语&#xff1a;half-interval search&#xff09;、对数搜索&#xff08;英语&#xff1a;logarithmic search&#xf…

MFC 常用控件

目录 一、控件的交互方式 二、CButton/CheckBox/RadioButton 三、EditControl 四、ListBox 五、ComBox 六、Progress/Timer 七、PictureController 八、ListControl 九、Tree 一、控件的交互方式 得到控件的类的对象&#xff0c;就可以通过这个对象来操作类 CWnd* G…

计算机毕业设计 基于SpringBoot的车辆网位置信息管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

【入门篇】1.4 redis 客户端 之 Lettuce 详解

文章目录 1. 简介1. 什么是Lettuce2. Lettuce与其他Redis客户端的比较3. Lettuce的特性和优势 2. 安装和配置3. 连接池配置1. 什么是连接池2. Lettuce的连接池使用与配置3. 连接池配置项 4. 基本操作1. 如何创建Lettuce连接2. Lettuce的基本操作如增删改查3. Lettuce的事务操作…

Halcon (2):Halcon基础知识

文章目录 文章专栏视频资源前言Halcon文档案例学习结论 文章专栏 Halcon开发 视频资源 机器视觉之C#联合Halcon 前言 本章我们主要讲解Halcon的基础语法 Halcon文档 按下F1&#xff0c;就可以看到Halcon的文档&#xff0c;不过都是纯英文的 如果不清楚参数如何使用&#x…

十三、Docker的安装

0.安装Docker Docker 分为 CE 和 EE 两大版本。CE 即社区版&#xff08;免费&#xff0c;支持周期 7 个月&#xff09;&#xff0c;EE 即企业版&#xff0c;强调安全&#xff0c;付费使用&#xff0c;支持周期 24 个月。 Docker CE 分为 stable test 和 nightly 三个更新频道…

异地工业设备集中运维、数据采集,一招搞定

为了提升运维效率&#xff0c;能够及时发现和响应设备的故障、异常和潜在问题。 越来越多的企业都在搭建“集中式”的远程智慧运维体系&#xff0c;以提高运维效率和降低成本。 异地工业设备远程运维&#xff0c;提升响应效率、降低运维成本 以国内陕西某机床公司为例&#xff…

Buildroot 添加 Qt 支持

Buildroot 添加 Qt 支持 lqonlylove 于 2022-12-03 13:37:34 发布 阅读量2.8k 收藏 12 点赞数3 分类专栏: 根文件系统制作 文章标签: qt buildroot 版权 ​编辑根文件系统制作专栏收录该内容 2 篇文章0 订阅 订阅专栏 一、制作根文件系统 Buildroot 制作根文件系统_l…

【IT杂谈】--数据中台和BI项目失败的原因分析--以M集团传统制造业为例

“我们这个BI怎么做成这副鸟样&#xff0c;他们还想要钱&#xff0c;我们的尾款是不可能付的。”这是我在G集团听到财务总监的抱怨。感觉类似于这种吐槽BI的话&#xff0c;我经常能够听到的。我正在经历第四家公司&#xff0c;有三家公司都上了BI分析平台&#xff0c;但是效果都…

plantuml最原始的主题如何设置

在startuml下一行添加 skin rose startuml skin rose:Hello world; :This is defined on several **lines**;enduml 效果如下&#xff1a; plantuml官网地址如下&#xff1a; ​​​​​​使用简单的文字描述画UML图的开源工具。轻松从简单的文字说明创建UML图。也有许多种可…

信号的机制——信号的发送与处理

对于硬件触发的&#xff0c;无论是中断&#xff0c;还是信号&#xff0c;肯定是先到内核的&#xff0c;然后内核对于中断和信号处理方式不同。一个是完全在内核里面处理完毕&#xff0c;一个是将信号放在对应的进程 task_struct 里信号相关的数据结构里面&#xff0c;然后等待进…

Leetcode—剑指Offer LCR 140.训练计划II【简单】

2023每日刷题&#xff08;三十三&#xff09; Leetcode—LCR 140.训练计划II 实现代码 /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/ struct ListNode* trainingPlan(struct ListNode* head, int cnt) {str…

【好奇心驱动力】ESP8266驱动SG90舵机开关灯

0.前言 ESP8266弄丢了好几个都忘记放在哪&#xff0c;重新买了个typeC接口的方便多了&#xff0c;看到驱动SG90舵机作为智能开关&#xff0c;简单复现了一下&#xff0c;代码比较简单&#xff0c;没有连接小爱同学或者其他语音助手。 1.实验方法 ESP8266连接SG90舵机&#x…

Java中的集合内容总结——Collection接口

集合概述 Java 集合可分为 Collection 和 Map 两大体系&#xff1a; Collection接口&#xff1a;用于存储一个一个的数据。 List子接口&#xff1a;用来存储有序的、可以重复的数据&#xff08;主要用来替换数组&#xff0c;"动态"数组&#xff09; 实现类&#xf…

gRPC 的原理 介绍带你从头了解gRPC

gRPC 的原理 什么是gRPC gRPC的官方介绍是&#xff1a;gRPC是一个现代的、高性能、开源的和语言无关的通用 RPC 框架&#xff0c;基于 HTTP2 协议设计&#xff0c;序列化使用PB(Protocol Buffer)&#xff0c;PB 是一种语言无关的高性能序列化框架&#xff0c;基于 HTTP2PB 保…

一起Talk Android吧(第五百五十三回:解析Retrofit返回的数据)

文章目录 1. 知识回顾2. 解析方法2.1 解析有效数据2.2 解析错误数据3. 示例代码4. 经验与总结4.1 经验分享4.2 内容总结各位看官们大家好,上一回中咱们说的例子是"Retrofit的基本用法",本章回中介绍的例子是" 如何解析Retrofit返回的数据"。闲话休提,言…

解决Redis分布式锁宕机出现不可靠问题-zookeeper分布式锁

核心思想&#xff1a;当客户端要获取锁&#xff0c;则创建节点&#xff0c;使用完锁&#xff0c;则删除该节点。 客户端获取锁时&#xff0c;在 lock 节点下创建临时顺序节点。然后获取 lock下面的所有子节点&#xff0c;客户端获取到所有的子节点之后&#xff0c;如果发现自己…

hcia学习:

视频学习&#xff1a; 第一部分&#xff1a;基础学习。 19——子网掩码。 27——防火墙配置&#xff1a; 32——企业级路由器配置&#xff1a; 基础实验完成&#xff1a;&#xff08;完成以下目录对应的实验&#xff0c;第一部分基础实验就完成。&#xff09; 方法&#xff…