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

news/2024/2/29 15:56:29/文章来源:https://blog.csdn.net/xueyushenzhou/article/details/135615274

前面我们介绍了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.luyixian.cn/news_show_926217.aspx

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

相关文章

MATLAB二维与三维绘图实验

本文MATLAB源码&#xff0c;下载后直接打开运行即可[点击跳转下载]-附实验报告https://download.csdn.net/download/Coin_Collecter/88740747 一、实验目的 掌握图形对象属性的基本操作。掌握利用图形对象进行绘图操作的方法。 二、实验内容 利用图形对象绘制曲线&#xff…

Java基础 - 黑马

我是南城余&#xff01;阿里云开发者平台专家博士证书获得者&#xff01; 欢迎关注我的博客&#xff01;一同成长&#xff01; 一名从事运维开发的worker&#xff0c;记录分享学习。 专注于AI&#xff0c;运维开发&#xff0c;windows Linux 系统领域的分享&#xff01; 知…

最佳实践分享:SQL性能调优

SQL性能调优是一个需要不断探索和实践的过程&#xff0c;旨在确保数据库查询的高效运行。本文将分享一些SQL性能调优的最佳实践&#xff0c;帮助您提升数据库性能&#xff0c;减少查询响应时间。 一、索引优化 索引是提高查询性能的关键。以下是一些关于索引优化的建议&#…

完全备份、增量备份、差异备份、binlog日志

1 案例1&#xff1a;完全备份与恢复 1.1 问题 练习物理备份与恢复练习mysqldump备份与恢复 1.2 方案 在数据库服务器192.168.88.50 练习数据的备份与恢复 1.3 步骤 实现此案例需要按照如下步骤进行。 步骤一&#xff1a;练习物理备份与恢复 冷备份&#xff0c;需停止数…

数据结构第十四弹---链式二叉树基本操作(下)

链式二叉树 1、翻转二叉树2、判断两棵树是否相同3、判断二叉树是否是单值二叉树4、对称二叉树5、判断二叉树是否是平衡二叉树6、判断二叉树是否是另一棵二叉树的子树7、二叉树的销毁8、二叉树的深度遍历8.1、前序遍历8.2、中序遍历8.3、后序遍历 9、二叉树的构造和遍历总结 1、…

Java中的JVM指令和Arthas以及Dump文件(jvisualvm和MemoryAnalyzer工具)整体分析

前言 前天线上服务器突然内存和CPU都爆掉了&#xff0c;两者都处于一种高负载的状态&#xff0c;而且还是周末的情况下&#xff0c;起初运维同事怀疑是用户数量暴增&#xff0c;但是数据面板上并没有出现很大的暴增现象&#xff0c;之前的服务器4G的内存都跑不满后面升到8G还是…

NFS网络共享服务存储

目录 一、NFS简介 1、NFS定义&#xff1a; 2、NFS的特点 3、NFS的优缺点 4、NFS的原理图示 二、服务端NFS配置文件&#xff1a;/etc/exports 三、实验&#xff1a;NFS共享存储服务配置 1、服务端安装nfs-utils与rpcbind软件包 2、服务端新建共享文件夹目录并赋予权限 …

【数据库】sql优化有哪些?从query层面和数据库层面分析

目录 归纳sql本身的优化数据库层面的优化 归纳 这类型问题可以称为&#xff1a;Query Optimization&#xff0c;从清华AI4DB的paper list中&#xff0c;该类问题大致可以分为&#xff1a; Query RewriterCardinality EstimationCost EstimationPlan Optimization 从中文的角…

排序算法9----计数排序(C)

计数排序是一种非比较排序&#xff0c;不比较大小 。 1、思想 计数排序又称为鸽巢原理&#xff0c;是对哈希直接定址法的变形应用。 2、步骤 1、统计数据&#xff1a;统计每个数据出现了多少次。&#xff08;建立一个count数组&#xff0c;范围从[MIN,MAX],MAX代表arr中…

网页屏幕适配通透了

一&#xff0c;如果设计尺寸固定 那就按照固定尺寸开发 一般都是1920*1080 二&#xff0c;需要适配多种像素屏幕&#xff08;大屏可视化&#xff09; 可使用媒体查询设置多套css样式或者使用自适应单位&#xff0c;%&#xff0c;vw&#xff0c;vh 最好解决方案rem&#xff…

Unity Shader 的模板测试效果

模板测试是渲染管线中逐片元操作的一环&#xff0c;它的作用是筛选出指定模板的片元&#xff0c;而不符合模板的片元会被舍弃&#xff0c;从而做到一个遮罩的效果。 以下是Unity中实践的一个效果&#xff1a; 场景中可以看出&#xff0c;熊模型和茶壶模型都在差不多的位置&am…

Kafka 的架构

实验过程 1.三个虚拟机中解压kafka软件包 tar -zxvf kafka_2.11-1.1.1.tgz 2.修改 3 个节点配置文件 在 zookeeper 节点&#xff0c;进入 kafka_2.11-1.1.1/config 目录下&#xff0c;编辑 server.properties 文件 [rootdb1 ~]# cd kafka_2.11-1.1.1/config [rootdb1 con…

HarmonyOS应用开发者高级认证试题库(鸿蒙)

目录 考试链接&#xff1a; 流程&#xff1a; 选择&#xff1a; 判断 单选 多选 考试链接&#xff1a; 华为开发者学堂华为开发者学堂https://developer.huawei.com/consumer/cn/training/dev-certification/a617e0d3bc144624864a04edb951f6c4 流程&#xff1a; 先进行…

【一】通信协议概述

通信协议概述 简介&#xff1a; 很早之前就思考了要写一下电力系统常用的几种通信协议&#xff0c;一直拖着也没有行动&#xff0c;这次终于下定决心来出一个《通信协议》这样的专栏。电力行业数字化方面资料较少&#xff0c;我理解主要一方面是数字化程度还不高&#xff0c;一…

使用Python操纵Word自动编写离职报告

目录 一、背景介绍 二、技术原理 三、实现步骤 1、安装python-docx库 2、创建Word文档 3、添加标题和内容 4、添加表格和图片 5、设置样式和格式化文本 6、保存文档 四、注意事项与建议 总结 随着现代社会的发展&#xff0c;自动化和智能化已经成为各行各业追求的目…

使用PyTorch实现混合专家(MoE)模型

Mixtral 8x7B 的推出在开放 AI 领域引发了广泛关注&#xff0c;特别是混合专家&#xff08;Mixture-of-Experts&#xff1a;MoEs&#xff09;这一概念被大家所认知。混合专家(MoE)概念是协作智能的象征&#xff0c;体现了“整体大于部分之和”的说法。MoE模型汇集了各种专家模型…

消息的发送与接收

消息的发送与接收 消息的发送与接收不仅仅是在于聊天功能的实现。其实还有很多种情况也算"消息的发送与接收"。而且我们还可以通过多种方法去实现。我们可以基于实际情况来选择。 WebSocket实现 node做后端。找了好多&#xff0c;前端页面总是用到了jQuery&#x…

(C语言)冒泡排序

一、运行结果&#xff1b; 二、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>//实现buble_sort函数&#xff1b; void buble_sort(int arr[], int sz) {//初始化变量值&#xff1b;int i 0;//嵌套循环冒泡排序&#xff1b;//外层循环&…

【REST2SQL】10 REST2SQL操作指南

【REST2SQL】01RDB关系型数据库REST初设计 【REST2SQL】02 GO连接Oracle数据库 【REST2SQL】03 GO读取JSON文件 【REST2SQL】04 REST2SQL第一版Oracle版实现 【REST2SQL】05 GO 操作 达梦 数据库 【REST2SQL】06 GO 跨包接口重构代码 【REST2SQL】07 GO 操作 Mysql 数据库 【RE…

微信小程序-----全局配置与页面配置

目录 前言 全局配置文件 一、window 1. 小程序窗口的组成部分 2. window 节点常用的配置项 3. 设置导航栏的标题 4. 设置导航栏的背景色 5. 设置导航栏的标题颜色 6. 全局开启下拉刷新功能 7. 设置下拉刷新时窗口的背景色 8. 设置下拉刷新时 loading 的样式 9. 设置…