【征服redis4】一文征服redis的Lettuce客户端

前面我们介绍了jedis客户端的使用,本文我们继续介绍第二个常用的客户端Lettuce。与jedis相比Lettuce有什么特征和区别,以及使用的时候有哪些重要的问题呢?本文我们一起来探究一下。

1. Lettuce介绍与安装测试


1.1. 什么是Lettuce

Lettuce是一个高级Redis客户端,用于线程安全的同步、异步和反应式访问。它支持高级的Redis特性,如Sentinel、集群、流水线、自动重新连接和redis数据模型等。Lettuce是完全非阻塞的,基于Netty事件驱动的通信层,其方法将返回具有可观察的类型,可在流或异步编程环境中使用。

Lettuce与其他Redis客户端的比较
与Jedis这种阻塞的Java Redis客户端相比,Lettuce的主要优势在于其完全非阻塞的IO和线程安全。使用Jedis,在多线程环境中,需要使用连接池以避免线程安全问题,但是对于Lettuce来说,可以避免这种复杂的设置,因为一个Lettuce连接实例(StatefulRedisConnection)就是线程安全的。另一个重要的区别是,Lettuce支持Redis的高级特性,如集群、流水线、发布订阅、和Lua脚本。

 Lettuce的特性和优势
完全非阻塞IO和线程安全:Lettuce使用Netty进行网络通信,采用了异步和事件驱动的模型。一个Lettuce连接实例(StatefulRedisConnection)是线程安全的,可以在多个线程间共享。
支持Redis的高级特性:Lettuce支持Redis的高级特性,如Sentinel、集群、流水线、发布订阅、Lua脚本等。
自动重连:Lettuce支持自动重连,当Redis服务器重新启动或断开连接时,Lettuce可以自动恢复连接。
可观察的数据类型:Lettuce的所有操作都返回Observable,这可以让在流或异步编程环境中使用。

1.2. 安装

在Java项目中,可以使用Maven或者Gradle来引入Lettuce的依赖。

使用Maven引入依赖

该工作与引入jedis是类似的,可以直接引入pom坐标:

        <dependency><groupId>io.lettuce</groupId><artifactId>lettuce-core</artifactId><version>6.1.5.RELEASE</version> </dependency>

配置Lettuce和使用的问题,我们下一个小节再看。

1.3 Lettuce 与Jedis的比较

这两个都是redis的常用客户端,那有什么区别和联系呢?我们一起来比较一下

维度/库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连接与使用

配置方式与JDBC类似,也非常简单,创建一个新的RedisClient实例,使用redis://password@localhost:6379/0作为Redis服务器的URL。如果我们设置了密码,可以将里面的password改成密码,没有密码的话,可以直接写成password。

然后我们打开一个新的连接,并通过此连接获取同步命令来执行Redis命令。执行完命令后,我们关闭了连接并关闭了Redis客户端。

完整代码如下:

    public static void main(String[] args) {// 初始化Redis客户端RedisClient redisClient = RedisClient.create("redis://password@localhost:6379/0");// 打开一个新的连接StatefulRedisConnection<String, String> connection = redisClient.connect();// 获取同步命令RedisCommands<String, String> syncCommands = connection.sync();// 执行命令syncCommands.set("key", "Hello World");String key= syncCommands.get("key");// 关闭连接connection.close();// 关闭Redis客户端redisClient.shutdown();}

上面的代码只能用来测试,在实际项目中,我们可以自己将连接的开闭过程封装一下,这样就不必在每个方法里都要自己创建和关闭连接了,我们可以简单地这么做:

    //    开闭连接封装public static StatefulRedisConnection<String, String> getConnection() {// 初始化Redis客户端redisClient = RedisClient.create("redis://password@localhost:6379/0");// 打开一个新的连接return redisClient.connect();}public static boolean closeConnection(StatefulRedisConnection<String, String> connection) {// 关闭连接connection.close();redisClient.shutdown();return true;}

然后使用的时候这么写:

    //    基本环境测试public static void initTest2() {// 初始化Redis客户端StatefulRedisConnection<String, String> redisConnection = getConnection();// 获取同步命令RedisCommands<String, String> syncCommands = redisConnection.sync();// 执行命令syncCommands.set("key", "Hello, Redis!");String key = syncCommands.get("key");System.out.println(key);closeConnection(redisConnection);}

这里只是做了简单的封装,看起来舒服一些。

2.2. 连接池的配置和使用

1. 什么是连接池
连接池是一个预先创建并存储数据库连接的容器,应用程序在需要与数据库交互时,可以从连接池中获取已经建立的连接。使用完毕后,将该连接归还给连接池,而不是关闭它。这种技术可以避免每次需要与数据库交互时都打开新的连接,节省了创建新连接所需的时间。连接池最经典的应用就是数据库连接池,不过除此之外,在通过网络连接其他服务等场景的时候,我们都会采用连接池技术。

Lettuce是一个基于Netty的高级Redis客户端,用于线程安全同步、异步和响应式通信。在Lettuce中,每次发送命令都会获取新的连接,执行完命令后就会关闭。这就是说,Lettuce本身并没有传统意义上的"连接池"。虽然在Lettuce本身并未实现连接池,但是在使用Spring Data Redis的情况下,可以通过配置LettuceConnectionFactory来实现连接池的效果。

在创建RedisClient或者RedisClusterClient之前,可以通过ClientResources.Builder来定制连接池的一些参数,如下所示:

    public static RedisClient connectPool() {// 创建一个ClientResources来定制连接池参数ClientResources clientResources = DefaultClientResources.builder().ioThreadPoolSize(16) // IO线程池大小.computationThreadPoolSize(16) // 计算线程池大小.build();// 使用定制的ClientResources来创建RedisClientreturn RedisClient.create(clientResources, "redis://localhost:6379");}

然后我们可以采用下面的代码来测试一下:

    //    连接池测试public static void initTest3() {// 初始化Redis客户端RedisClient redisClient1=connectPool();StatefulRedisConnection<String, String> redisConnection =redisClient1.connect() ;// 获取同步命令RedisCommands<String, String> syncCommands = redisConnection.sync();// 执行命令syncCommands.set("key2", "Hello, Redis!");String key = syncCommands.get("key2");System.out.println(key);redisConnection.close();redisClient1.shutdown();}

对于更复杂的需求,如最大连接数、最小空闲连接数等,Lettuce本身并没有提供对应的配置项。Lettuce的设计理念是每个Redis命令都运行在一个独立的连接上,因此并没有传统意义上的“连接池”。可以根据自己的需求,通过控制并发命令的数量来间接控制连接数量。

然而,如果正在使用Spring Data Redis,那么在Spring Data Redis中,可以通过LettucePoolingClientConfiguration来配置连接池(包括最大连接数、最小空闲连接数等),如下所示:
 

import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder().poolConfig(new GenericObjectPoolConfig()).build();RedisStandaloneConfiguration serverConfig = new RedisStandaloneConfiguration("server", 6379);LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(serverConfig, clientConfig);

在上面的代码中,我们使用LettucePoolingClientConfiguration.builder()来创建一个LettuceClientConfiguration的Builder,并使用poolConfig()方法来设置连接池配置。然后,我们使用这个配置和服务器配置来创建一个新的LettuceConnectionFactory。
 

2.3. 连接池配置项

配置Lettuce的连接池可以通过LettuceConnectionFactory类来实现。下面是配置连接池的一些常用参数:

1.最大连接数(MaxConnections):指定连接池的最大连接数,即同时能够从连接池中获取的最大连接数。可以使用setConnectionPoolConfiguration()方法来设置。

GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
poolConfig.setMaxTotal(maxConnections);
lettuceConnectionFactory.setPoolConfig(poolConfig);

2.最小空闲连接数(MinIdleConnections):指定连接池中的最小空闲连接数,即连接池中保持的最少可用连接数。可以使用setPoolConfig()方法来设置。

GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
poolConfig.setMinIdle(minIdleConnections);
lettuceConnectionFactory.setPoolConfig(poolConfig);

3.连接空闲超时时间(IdleTimeout):指定连接在空闲状态下的超时时间,超过该时间会被连接池回收。可以使用`setTimeout()`方法来设置。

lettuceConnectionFactory.setTimeout(idleTimeout);

4.连接重试次数(RetryAttempts):指定在连接池无法获取到可用连接时的重试次数。可以使用setRetryAttempts()方法来设置。

lettuceConnectionFactory.setRetryAttempts(retryAttempts);

5.连接重试间隔时间(RetryInterval):指定连接重试的间隔时间,即每次重试之间的等待时间。可以使用setRetryInterval()方法来设置。

lettuceConnectionFactory.setRetryInterval(retryInterval);

以上是一些常用的连接池参数的配置方法。根据实际需求,您可以根据需要设置这些参数来优化连接池的性能。

2.4 Lettuce的基本操作如增删改查

可以使用RedisCommands的对应方法进行操作。例如:

RedisCommands<String, String> syncCommands = connection.sync();
// 添加键值对
syncCommands.set("key", "value");
// 获取键值对
String value = syncCommands.get("key");
// 删除键值对
syncCommands.del("key");
// 修改键值对
syncCommands.set("key", "newValue");

2.5. Lettuce的事务操作

Lettuce支持事务操作,可以使用multi()和exec()方法进行事务的开始和提交:

RedisCommands<String, String> syncCommands = connection.sync();
// 开启事务
syncCommands.multi();
syncCommands.set("key1", "value1");
syncCommands.set("key2", "value2");
// 提交事务
syncCommands.exec();

2.6. Lettuce的管道操作

Lettuce支持管道操作,可以使用RedisCommandsautoFlushCommands()方法来关闭自动刷新,然后用flushCommands()方法来手动刷新:

RedisCommands<String, String> syncCommands = connection.sync();
syncCommands.setAutoFlushCommands(false);
syncCommands.set("key1", "value1");
syncCommands.set("key2", "value2");
syncCommands.flushCommands();

2.7. Lettuce的发布订阅操作

Lettuce支持Redis的发布订阅模式,例如:

RedisCommands<String, String> syncCommands = connection.sync();
// 订阅频道
RedisPubSubCommands<String, String> pubSubCommands = connection.sync();
pubSubCommands.subscribe("channel");
// 发布消息
syncCommands.publish("channel", "message");

2.8. Lettuce的脚本执行

Lettuce支持Lua脚本,可以使用RedisScriptingCommands的eval()或evalsha()方法来执行脚本

RedisScriptingCommands<String, String> scriptingCommands = connection.sync();
// 执行Lua脚本
String result = scriptingCommands.eval("return redis.call('get', KEYS[1])", ScriptOutputType.VALUE, new String[]{"key"});

注意:以上代码示例假设你已经有了一个有效的StatefulRedisConnection<String, String>对象。

2.9. 错误处理和重试

Lettuce的错误处理机制和重试策略,如何处理连接错误和命令执行失败等情况。

import io.lettuce.core.RedisClient;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.RedisCommandExecutionException;
import io.lettuce.core.RedisConnectionException;
import io.lettuce.core.RedisCommandInterruptedException;
import io.lettuce.core.RedisCommandTimeoutException;public class RedisExample {public static void main(String[] args) {RedisClient redisClient = RedisClient.create("redis://localhost:6379/");try {StatefulRedisConnection<String, String> connection = redisClient.connect();try {String result = connection.sync().get("key");System.out.println(result);} catch (RedisCommandExecutionException e) {System.err.println("Command execution failed: " + e.getMessage());} catch (RedisCommandInterruptedException e) {System.err.println("Command interrupted: " + e.getMessage());} catch (RedisCommandTimeoutException e) {System.err.println("Command timed out: " + e.getMessage());} finally {connection.close();}} catch (RedisConnectionException e) {System.err.println("Failed to connect to Redis: " + e.getMessage());} finally {redisClient.shutdown();}}
}

2.10 redis常见与处理方法

异常名称说明处理方法
RedisConnectionException当无法连接到Redis服务器时,或在尝试发送命令时连接已关闭或断开,将抛出此异常。检查你的Redis服务器是否正在运行,网络连接是否畅通。如果是因为连接已关闭或断开,可以尝试重新连接。
RedisCommandTimeoutException当命令的执行超过设定的超时时间时,将抛出此异常。可以尝试增加命令的超时时间,或者查看Redis服务器是否有性能问题,如CPU使用过高,磁盘IO过高等。
RedisCommandInterruptedException当等待命令完成的过程中线程被中断,将抛出此异常。可以查看线程为何被中断,并尝试解决中断的原因。
RedisCommandExecutionException当Redis命令执行失败时(如键不存在,类型不匹配等),将抛出此异常。检查你的Redis命令是否正确,如键是否存在,类型是否匹配等。如果命令没有问题,则可能是Redis服务器的问题,需要检查服务器的状况。

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

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

相关文章

详解toLowerCase(判断字符串相等)

一、toLowerCase 函数简介 toLowerCase() 是一个在多个编程语言中都存在的字符串方法&#xff0c;它的作用是将字符串中的所有大写字母转换为对应的小写字母。 常用于文本处理、搜索和比较等情况&#xff0c;以确保字符串的一致性和非大小写敏感的操作。 二、判断字符串相等 下…

(202401)深度强化学习基础与实践1:马尔科夫过程、DNQ算法回顾

文章目录 序言马尔科夫决策过程含义性质回报状态转移矩阵 DQN算法深度网络经验回放目标网络实战DQN算法 DQN 算法进阶Double DQNDueling DQNNoisy DQNPER DQNC51 算法 序言 本文章记录Datawhale开源学习组织2024年第一期学习&#xff0c;《深度强化学习基础与实践》第二期的任…

金属由液体凝固成液体,由于液体凝固为固体时,体积会缩小,导致金属铸造不可避免出现缩孔现象吗?

问题描述&#xff1a;金属由液体凝固成液体&#xff0c;由于液体凝固为固体时&#xff0c;体积会缩小&#xff0c;导致金属铸造不可避免出现缩孔现象吗&#xff1f; 问题解答&#xff1a; 在金属铸造过程中&#xff0c;确实存在由于液态金属凝固成为固态时体积收缩而导致缩孔…

mysql Linux系统云服务器配置远程访问

mysql Linux系统云服务器配置远程访问 1.安装mysql 服务器 2.配置远程登录用户权限 3.进行远程登录&#xff0c;并访问数据库 1.安装mysql 服务器 首先先安装一下云服务器 sudo apt-get install mysql-server安装好之后&#xff0c;我们直接以root用户登录&#xff1a; …

java set集合和list集合的区别

Java 中的 Set 集合和 List 集合都是用于存储一组元素的容器&#xff0c;但它们之间存在一些重要的区别。 元素唯一性&#xff1a;Set 集合中的元素是唯一的&#xff0c;不允许重复。而 List 集合中的元素可以重复。元素顺序&#xff1a;List 集合中的元素保持了它们被添加的顺…

大学生应该优先学技术还是准备考研

最近看到过不少人问这个问题&#xff0c;说实话哪一个优先级更高其实是要根据不同行业具体分析的&#xff0c;例如医药或者师范这类文凭跟工资直接挂钩的行业自然是考研优先级要高一些&#xff0c;但是CSDN这边的用户应该是计算机之类的技术专业较多&#xff0c;一般这种工作更…

EXEC sp_addlinkedserver 指定服务器ip

要使用 sp_addlinkedserver 存储过程在 SQL Server 中指定服务器 IP 地址&#xff0c;你可以在 datasrc 参数中提供服务器 IP 地址。以下是一个示例&#xff1a; EXEC sp_addlinkedserver server LinkToServer2, provider SQLNCLI, datasrc 192.168.0.1, -- 这里是目标服务器…

Vim一键配置指南,打造高效率C++开发环境

文章目录 前言安装与卸载功能演示gcc/g升级问题 前言 Vim作为当下最受欢迎的文本编译器之一&#xff0c;不仅具有强大的文本编辑功能&#xff0c;还提供了高度的可定制性。用户可以根据自己的喜好自定义配置&#xff0c;并且通过自己编写插件或者使用现有的插件来扩展Vim的功能…

【STM32】STM32学习笔记-I2C通信外设(34)

00. 目录 文章目录 00. 目录01. I2C简介02. I2C外设简介03. I2C框图04. I2C基本结构05. 主机发送06. 主机接收07. 软件/硬件波形对比08. 预留09. 附录 01. I2C简介 I2C(Inter&#xff0d;Integrated Circuit)总线是一种由NXP&#xff08;原PHILIPS&#xff09;公司开发的两线式…

黑马程序员——javase基础——day02——运算符选择语句

目录&#xff1a; 运算符 算术运算符案例数值拆分操作的三种情况 数字相加(类型转换)字符相加字符串相加赋值运算符选择语句 顺序结构Debug的基本使用选择语句之if if语句格式1if语句格式2和格式3案例1(交通信号灯)关系运算符案例2(奇偶数)案例3(手机以旧换新)案例4(你是青年人…

The Parade

Berland军队正在为一场大型阅兵式做准备。已经决定&#xff0c;参与其中的士兵将被分为k行&#xff0c;所有行都将包含相同数量的士兵。 当然&#xff0c;并不是每一次把士兵排成k排都是合适的。同一排中所有士兵的身高差异不应超过1。每个士兵的身高是一个介于1和n之间的整数。…

OpenCV-Python(42):摄像机标定

目标 学习摄像机畸变以及摄像机的内部参数和外部参数根据摄像机相关参数对畸变图像进行修复 基础说明 今天的低价单孔摄像机(照相机)会给图像带来很多畸变。畸变主要有两种:径向畸变和切向畸变。如下图所示用红色直线将棋盘的两个边标注出来&#xff0c;但是你会发现棋盘的边…

小程序样例1:简单待办列表

基本功能&#xff1a; 显示所有待办列表&#xff08;点击不同的文本进行显示&#xff09; 没完成的待办 已完成的待办 新建待办test 清除待办foo 代码js文件&#xff1a; //index.js //获取应用实例 const app getApp(); Page({data: {todo: ,todos: [{"id": 1474…

NanoPi NEO Air 配置指南

近期淘了块非常小巧的开发板 NaoPi NEO Air&#xff0c;这块板子仅有 40mm x 40mm 大小&#xff0c;除了一个 MicroUSB OTG 接口外如果想要扩展USB口就得使用左侧排针增加USB接口了。 关于 NanoPi NEO Air NanoPi NEO Air是一款基于全志H3四核A7主控的开源无线创客板&#xff…

SDRAM小项目——命令解析模块

简单介绍&#xff1a; 在FPGA中实现命令解析模块&#xff0c;命令解析模块的用来把pc端传入FPGA中的数据分解为所需要的数据和触发命令&#xff0c;虽然代码不多&#xff0c;但是却十分重要。 SDRAM的整体结构如下&#xff0c;可以看出&#xff0c;命令解析模块cmd_decode负责…

打造舒适的终端环境:我的.tmux.conf配置分享

打造舒适的终端环境&#xff1a;我的.tmux.conf配置分享 大家好&#xff0c;今天我来和大家分享一下我个人的 tmux 配置文件&#xff08;.tmux.conf&#xff09;&#xff0c;通过这份配置文件&#xff0c;你可以在终端中获得更加愉悦的使用体验。废话不多说&#xff0c;让我们…

springcloud-cloud provider-payment8001微服务提供者支付Module模块

文章目录 IDEA新建project工作空间cloud-provider-payment8001微服务提供者支付Module模块建表SQL测试 IDEA新建project工作空间 微服务cloud整体聚合父工程Project 写pom文件 <?xml version"1.0" encoding"UTF-8"?><project xmlns"htt…

一文就知道uniapp等跨端开发的使用场景,学习成本,如何快速使用,基本语法等

文章目录 一、简介二、uniapp用在哪些企业三、学习成本四、本次课程概括五、相关文档和学习资料六、快速使用七、Uni-app的基本语法八、项目实战 一、简介 是一个跨平台开发各种各样应用的一套框架。只需要写一套代码&#xff0c;可以适配多达14种产品类型&#xff0c;比如H5移…

1月16日,每日信息差

​第一、苹果将推出欧盟特供版App Store。由于这些变化&#xff0c;App Store将被一分为二&#xff0c;欧盟国家有一个版本&#xff0c;世界其他地区将是另一个版本。欧盟的新法规《数字市场法案》&#xff08;DMA&#xff09;要求苹果允许开发者在App Store之外发布他们的iOS应…

[足式机器人]Part2 Dr. CAN学习笔记-Advanced控制理论 Ch04-9 可观测性与分离原理

本文仅供学习使用 本文参考&#xff1a; B站&#xff1a;DR_CAN Dr. CAN学习笔记-Advanced控制理论 Ch04-9 可观测性与分离原理