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

文章目录

  • 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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

多媒体ffmpeg学习教程

多媒体ffmpeg 目前比较流行的音视频文件为:MP4 flv m3u8 ffmpeg ffmpeg ffplay ffprobe ffserverffmpeg -i INPUT -vf "split [main][tmp]; [tmp] cropiw:ih/2:0:0, vflip [flip];[main][flip] overlay0:H/2" OUTPUTffmpeg -i 2022.mp4 -vcodec mpeg4 -b:…

YOLO目标检测——无人机检测数据集下载分享【含对应voc、coco和yolo三种格式标签】

实际项目应用&#xff1a;无人机识别数据集说明&#xff1a;无人机检测数据集&#xff0c;真实场景的高质量图片数据&#xff0c;数据场景丰富标签说明&#xff1a;使用lableimg标注软件标注&#xff0c;标注框质量高&#xff0c;含voc(xml)、coco(json)和yolo(txt)三种格式标签…

软件安利——火绒安全

近年来&#xff0c;以优化、驱动、管理为目标所打造的软件屡见不鲜&#xff0c;大同小异的电脑管家相继走入了公众的视野。然而&#xff0c;在这日益急功近利的社会氛围驱动之下&#xff0c;真正坚持初心、优先考虑用户体验的电脑管家逐渐湮没在了浪潮之中。无论是鲁大师&#…

2023年【P气瓶充装】报名考试及P气瓶充装复审考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年P气瓶充装报名考试为正在备考P气瓶充装操作证的学员准备的理论考试专题&#xff0c;每个月更新的P气瓶充装复审考试祝您顺利通过P气瓶充装考试。 1、【多选题】充装过程中出现充气头漏气的主要原因为&#xff1…

python 对图像进行聚类分析

import cv2 import numpy as np from sklearn.cluster import KMeans import time# 中文路径读取 def cv_imread(filePath, cv2_falgcv2.COLOR_BGR2RGB): cv_img cv2.imdecode(np.fromfile(filePath, dtypenp.uint8), cv2_falg) return cv_img# 自定义装饰器计算时间 def…

C++知识点总结(6):高精度乘法

一、高精度数 低精度数 1. 输入两个数字 char a_str[1005] {}; long long b; cin >> a_str >> b; 2. 将高精度数转换为整型 int a[1005] {}; int len_a strlen(a_str); for (int i 0; i < len_a-1; i) {a[len_a-i-1] a_str[i] - 48; } 3. 计算 int …

2.3 调用智谱 API

调用智谱 API 1 申请调用权限2 调用智谱 AI API3 使用 LangChain 调用智谱 AI参考&#xff1a; 智谱 AI 是由清华大学计算机系技术成果转化而来的公司&#xff0c;致力于打造新一代认知智能通用模型。公司合作研发了双语千亿级超大规模预训练模型 GLM-130B&#xff0c;并构建了…

【Python】Loguru模块更简洁的日志记录库

Loguru: 更优雅的日志记录解决方案&#xff01; loguru 是一个Python 简易且强大的第三方日志记录库&#xff0c;该库旨在通过添加一系列有用的功能来解决标准记录器的注意事项&#xff0c;从而减少 Python 日志记录的痛苦。 使用自带自带的 logging 模块的话&#xff0c;则需要…

机器学习笔记 - 使用 PyTorch 的多任务学习和 HydraNet

一、HydraNet简述 特斯拉使用了一个模型可以解决他们正在处理的每一项可能的任务。 例如:物体检测、道路曲线估计、深度估计、3D重建、视频分析、物体追踪、ETC等等。 以下是在 NVIDIA GPU 上以 3 种不同配置运行的 2 个计算机视觉模型的基准测试。 在第一个配置中,我…

柯桥会计培训|中级会计职称,考过中级,可以从事哪些工作?

拿下中级会计证书后&#xff0c;可以从事哪些工作呢&#xff1f;一起来看看吧~ 财务经理 财务经理可以说是会计人梦寐以求的岗位&#xff0c;上可以和老板畅聊公司财务情况&#xff0c;下可以管理整个财务部。但是在财务管理水平日益成为企业核心竞争力的今天&#xff0c;企业…

软件工程--软件过程学习笔记

本篇内容是对学校软件工程课堂内容的记录总结&#xff0c;部分也来源于网上查找的资料 软件过程基础 软件过程是指在软件开发过程中&#xff0c;经过一系列有序的步骤和活动&#xff0c;从问题定义到最终软件产品交付和维护的全过程。这个过程旨在确保软件项目能够按时、按预…

AWS EC2、阿里云ECS、腾讯云CVM初步对比

作为国内外的头部云厂商&#xff0c;AWS、阿里云、腾讯云都有着相似功能的云产品&#xff0c;而作为云上最基础的资源就是云服务器——一种简单高效、安全可靠、处理能力可弹性伸缩的计算服务。其管理方式比物理服务器更简单高效。用户无需提前购买硬件&#xff0c;即可迅速创建…

QtCreator开发环境的安装和配置

QtCreator开发环境的安装和配置 介绍下载与安装环境介绍示例新建工程示例程序 帮助模式Qt Designer(设计师)Qt Linguist(预言家)结论 介绍 Qt Creator是一个跨平台、完整的集成开发环境&#xff08;IDE&#xff09;&#xff0c;专门用于Qt开发。它包含了完整的编辑器、调试器和…

电子电器架构 —— 车载网关边缘节点总线转换

电子电器架构 —— 车载网关边缘节点路由转发策略 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 PS:小细节,本文字数3000+,详细描述了网关在车载框架中的具体性能设置。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 没有人关注你。也无…

【C/C++笔试练习】继承和派生的概念、虚函数的概念、派生类的析构函数、纯虚函数的概念、动态编译、多态的实现、参数解析、跳石板

文章目录 C/C笔试练习选择部分&#xff08;1&#xff09;继承和派生的概念&#xff08;2&#xff09;程序分析&#xff08;3&#xff09;虚函数的概念&#xff08;4&#xff09;派生类的析构函数&#xff08;5&#xff09;纯虚函数的概念&#xff08;6&#xff09;动态编译&…

docker 安装mongodb 实现 数据,日志,配置文件外挂

docker 安装mongodb 实现数据&#xff0c;日志&#xff0c;配置文件外挂 1 背景 最近开发了一个评论系统之前用mysql来存储数据&#xff0c;但是考虑到后期业务增大访问量也会增大&#xff0c;为了兼容这种高并发的场景&#xff0c;因此经过多方面的考虑&#xff0c;我们最终…

python中的NumPy和Pandas往往都是同时使用,NumPy和Pandas的在数据分析中的联合使用

文章目录 前言一、numpy的介绍与用法二、pandas的介绍与用法三、numpy与pandas的联合使用说明四、numpy与pandas的联合使用程序代码4.1 读取CSV文件并进行数据清洗&#xff0c;如去除NaN值4.2 矩阵操作和特征工程&#xff0c;如标准化处理4.3 使用Pandas进行数据筛选和分组聚合…

Vue3-shallowRef 和 shallowReactive函数(浅层次的响应式)

Vue3-shallowRef 和 shallowReactive函数&#xff08;浅层次的响应式&#xff09; shallowRef函数 功能&#xff1a;只给基本数据类型添加响应式。如果是对象&#xff0c;则不会支持响应式&#xff0c;层成也不会创建Proxy对象。ref和shallowRef在基本数据类型上是没有区别的…

Typora——优雅的排版也是一种品味

电脑中用于编辑文本的软件&#xff0c;一直以来可谓是层出不穷&#xff0c;大家脑海中一定会浮现出很多名字&#xff1a;word&#xff0c;OneNote&#xff0c;记事本&#xff0c;wps&#xff0c;LaTeX&#xff0c;还有各种小众的office工具&#xff0c;等等等等。今天学长将介绍…

人充当LLM Agent的工具(Human-In-The-Loop ),提升复杂问题解决成功率

原文&#xff1a;人充当LLM Agent的工具&#xff08;Human-In-The-Loop &#xff09;&#xff0c;提升复杂问题解决成功率 在Agent开发过程中&#xff0c;LLM充当Agent的大脑&#xff0c;对问题进行规划、分解、推理&#xff0c;在执行过程中合理选择利用工具&#xff08;Tool&…