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

打印 上一主题 下一主题

主题 658|帖子 658|积分 1974


1. 简介

1. 什么是Lettuce

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

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



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

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

  • 使用Maven引入依靠
  1. <dependency>
  2.     <groupId>io.lettuce</groupId>
  3.     <artifactId>lettuce-core</artifactId>
  4.     <version>6.1.5.RELEASE</version> <!-- 请将此版本号替换为所需要的版本 -->
  5. </dependency>
复制代码

  • 使用Gradle引入依靠
  1. dependencies {
  2.     implementation 'io.lettuce:lettuce-core:6.1.5.RELEASE'  
  3. }
复制代码
  配置Lettuce非常简单
创建一个新的RedisClient实例,使用redis://password@localhost:6379/0作为Redis服务器的URL。然后我们打开一个新的连接,并通过此连接获取同步命令来执行Redis命令。执行完命令后,我们关闭了连接并关闭了Redis客户端。
  1. import io.lettuce.core.RedisClient;
  2. import io.lettuce.core.api.StatefulRedisConnection;
  3. import io.lettuce.core.api.sync.RedisCommands;
  4. public class Example {
  5.     public static void main(String[] args) {
  6.         // 初始化Redis客户端
  7.         RedisClient redisClient = RedisClient.create("redis://password@localhost:6379/0");
  8.         // 打开一个新的连接
  9.         StatefulRedisConnection<String, String> connection = redisClient.connect();
  10.         // 获取同步命令
  11.         RedisCommands<String, String> syncCommands = connection.sync();
  12.         // 执行命令
  13.         syncCommands.set("key", "Hello, Redis!");
  14.         // 关闭连接
  15.         connection.close();
  16.         // 关闭Redis客户端
  17.         redisClient.shutdown();
  18.     }
  19. }
复制代码
3. 连接池配置

1. 什么是连接池

连接池是一个预先创建并存储数据库连接的容器,应用程序在需要与数据库交互时,可以从连接池中获取已经创建的连接。使用完毕后,将该连接归还给连接池,而不是关闭它。这种技术可以避免每次需要与数据库交互时都打开新的连接,节流了创建新连接所需的时间。
Lettuce是一个基于Netty的高级Redis客户端,用于线程安全同步、异步和响应式通讯。在Lettuce中,每次发送命令都会获取新的连接,执行完命令后就会关闭。这就是说,Lettuce自己并没有传统意义上的"连接池"。
2. Lettuce的连接池使用与配置

虽然在Lettuce自己并未实现连接池,但是在使用Spring Data Redis的情况下,可以通过配置LettuceConnectionFactory来实现连接池的效果。
以下是一个配置示例:
  1. import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
  2. import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
  3. // 创建连接池配置
  4. LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder()
  5.     .poolConfig(new GenericObjectPoolConfig())
  6.     .build();
  7. // 创建服务器配置
  8. RedisStandaloneConfiguration serverConfig = new RedisStandaloneConfiguration("localhost", 6379);
  9. // 使用这两种配置创建Lettuce连接工厂
  10. LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(serverConfig, clientConfig);
复制代码
在这个配置中,我们使用LettucePoolingClientConfiguration.builder()来创建一个LettuceClientConfiguration的Builder,并使用poolConfig()方法来设置连接池配置。然后,我们使用这个配置和服务器配置来创建一个新的LettuceConnectionFactory。
留意,GenericObjectPoolConfig可以让设置一些连接池的参数,比方maxTotal(最大连接数),maxIdle(最多的空闲连接数),minIdle(最少的空闲连接数)等等。
在Lettuce中,使用RedisClient或者RedisClusterClient创建的基本连接实际上是一个连接池。可以通过ClientOptions和ClientResources来定制连接池的行为。
默认连接池的行为如下:

  • 默认情况下,连接池巨细为8个连接。
  • 连接尝试失败后,默认重试时间间隔为30秒。
在创建RedisClient或者RedisClusterClient之前,可以通过ClientResources.Builder来定制连接池的一些参数,如下所示:
  1. import io.lettuce.core.RedisClient;
  2. import io.lettuce.core.resource.ClientResources;
  3. import io.lettuce.core.resource.DefaultClientResources;
  4. public class Example {
  5.     public static void main(String[] args) {
  6.         // 创建一个ClientResources来定制连接池参数
  7.         ClientResources clientResources = DefaultClientResources.builder()
  8.             .ioThreadPoolSize(16) // IO线程池大小
  9.             .computationThreadPoolSize(16) // 计算线程池大小
  10.             .build();
  11.         // 使用定制的ClientResources来创建RedisClient
  12.         RedisClient redisClient = RedisClient.create(clientResources, "redis://localhost:6379");
  13.         // 其他代码...
  14.     }
  15. }
复制代码
对于更复杂的需求,如最大连接数、最小空闲连接数等,Lettuce自己并没有提供对应的配置项。Lettuce的计划理念是每个Redis命令都运行在一个独立的连接上,因此并没有传统意义上的“连接池”。可以根据自己的需求,通过控制并发命令的数量来间接控制连接数量。
然而,假如正在使用Spring Data Redis,那么在Spring Data Redis中,可以通过LettucePoolingClientConfiguration来配置连接池(包括最大连接数、最小空闲连接数等),如下所示:
  1. import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
  2. import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
  3. LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder()
  4.     .poolConfig(new GenericObjectPoolConfig())
  5.     .build();
  6. RedisStandaloneConfiguration serverConfig = new RedisStandaloneConfiguration("server", 6379);
  7. LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(serverConfig, clientConfig);
复制代码
在上面的代码中,我们使用LettucePoolingClientConfiguration.builder()来创建一个LettuceClientConfiguration的Builder,并使用poolConfig()方法来设置连接池配置。然后,我们使用这个配置和服务器配置来创建一个新的LettuceConnectionFactory。
3. 连接池配置项

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

  • 最大连接数(MaxConnections):指定连接池的最大连接数,即同时可以或许从连接池中获取的最大连接数。可以使用setConnectionPoolConfiguration()方法来设置。
  1. GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
  2. poolConfig.setMaxTotal(maxConnections);
  3. lettuceConnectionFactory.setPoolConfig(poolConfig);
复制代码

  • 最小空闲连接数(MinIdleConnections):指定连接池中的最小空闲连接数,即连接池中保持的最少可用连接数。可以使用setPoolConfig()方法来设置。
  1. GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
  2. poolConfig.setMinIdle(minIdleConnections);
  3. lettuceConnectionFactory.setPoolConfig(poolConfig);
复制代码

  • 连接空闲超时时间(IdleTimeout):指定连接在空闲状态下的超时时间,凌驾该时间会被连接池接纳。可以使用setTimeout()方法来设置。
  1. lettuceConnectionFactory.setTimeout(idleTimeout);
复制代码

  • 连接重试次数(RetryAttempts):指定在连接池无法获取到可用连接时的重试次数。可以使用setRetryAttempts()方法来设置。
  1. lettuceConnectionFactory.setRetryAttempts(retryAttempts);
复制代码

  • 连接重试间隔时间(RetryInterval):指定连接重试的间隔时间,即每次重试之间的等待时间。可以使用setRetryInterval()方法来设置。
  1. lettuceConnectionFactory.setRetryInterval(retryInterval);
复制代码
以上是一些常用的连接池参数的配置方法。根据实际需求,您可以根据需要设置这些参数来优化连接池的性能。
4. 基本操作

1. 如何创建Lettuce连接

你可以使用RedisClient或RedisClusterClient的connect()方法来创建一个连接。比方:
  1. RedisClient redisClient = RedisClient.create("redis://localhost:6379");
  2. StatefulRedisConnection<String, String> connection = redisClient.connect();
复制代码
2. Lettuce的基本操作如增编削查

可以使用RedisCommands的对应方法进行操作。比方:
  1. RedisCommands<String, String> syncCommands = connection.sync();
  2. // 添加键值对
  3. syncCommands.set("key", "value");
  4. // 获取键值对
  5. String value = syncCommands.get("key");
  6. // 删除键值对
  7. syncCommands.del("key");
  8. // 修改键值对
  9. syncCommands.set("key", "newValue");
复制代码
3. Lettuce的事件操作

Lettuce支持事件操作,可以使用multi()和exec()方法进行事件的开始和提交:
  1. RedisCommands<String, String> syncCommands = connection.sync();
  2. // 开启事务
  3. syncCommands.multi();
  4. syncCommands.set("key1", "value1");
  5. syncCommands.set("key2", "value2");
  6. // 提交事务
  7. syncCommands.exec();
复制代码
4. Lettuce的管道操作

Lettuce支持管道操作,可以使用RedisCommands的autoFlushCommands()方法来关闭自动刷新,然后用flushCommands()方法来手动刷新:
  1. RedisCommands<String, String> syncCommands = connection.sync();
  2. syncCommands.setAutoFlushCommands(false);
  3. syncCommands.set("key1", "value1");
  4. syncCommands.set("key2", "value2");
  5. syncCommands.flushCommands();
复制代码
5. Lettuce的发布订阅操作

Lettuce支持Redis的发布订阅模式,比方:
  1. RedisCommands<String, String> syncCommands = connection.sync();
  2. // 订阅频道
  3. RedisPubSubCommands<String, String> pubSubCommands = connection.sync();
  4. pubSubCommands.subscribe("channel");
  5. // 发布消息
  6. syncCommands.publish("channel", "message");
复制代码
6. Lettuce的脚本执行

Lettuce支持Lua脚本,可以使用RedisScriptingCommands的eval()或evalsha()方法来执行脚本:
  1. RedisScriptingCommands<String, String> scriptingCommands = connection.sync();
  2. // 执行Lua脚本
  3. String result = scriptingCommands.eval("return redis.call('get', KEYS[1])", ScriptOutputType.VALUE, new String[]{"key"});
复制代码
留意:以上代码示例假设你已经有了一个有用的StatefulRedisConnection<String, String>对象。
5. 错误处置惩罚和重试

Lettuce的错误处置惩罚机制和重试策略,如何处置惩罚连接错误和命令执行失败等情况。
  1. import io.lettuce.core.RedisClient;
  2. import io.lettuce.core.api.StatefulRedisConnection;
  3. import io.lettuce.core.RedisCommandExecutionException;
  4. import io.lettuce.core.RedisConnectionException;
  5. import io.lettuce.core.RedisCommandInterruptedException;
  6. import io.lettuce.core.RedisCommandTimeoutException;
  7. public class RedisExample {
  8.     public static void main(String[] args) {
  9.         RedisClient redisClient = RedisClient.create("redis://localhost:6379/");
  10.         try {
  11.             StatefulRedisConnection<String, String> connection = redisClient.connect();
  12.             
  13.             try {
  14.                 String result = connection.sync().get("key");
  15.                 System.out.println(result);
  16.             } catch (RedisCommandExecutionException e) {
  17.                 System.err.println("Command execution failed: " + e.getMessage());
  18.             } catch (RedisCommandInterruptedException e) {
  19.                 System.err.println("Command interrupted: " + e.getMessage());
  20.             } catch (RedisCommandTimeoutException e) {
  21.                 System.err.println("Command timed out: " + e.getMessage());
  22.             } finally {
  23.                 connection.close();
  24.             }
  25.         } catch (RedisConnectionException e) {
  26.             System.err.println("Failed to connect to Redis: " + e.getMessage());
  27.         } finally {
  28.             redisClient.shutdown();
  29.         }
  30.     }
  31. }
复制代码
1. Lettuce的常见非常

  • RedisConnectionException:当无法连接到Redis服务器时,或在尝试发送命令时连接已关闭或断开,将抛出此非常。
  • RedisCommandTimeoutException:当命令的执行凌驾设定的超时时间时,将抛出此非常。
  • RedisCommandInterruptedException:当等待命令完成的过程中线程被停止,将抛出此非常。
  • RedisCommandExecutionException:当Redis命令执行失败时(如键不存在,类型不匹配等),将抛出此非常。
2. 如何处置惩罚这些非常

  • RedisConnectionException:查抄你的Redis服务器是否正在运行,网络连接是否畅通。假如是因为连接已关闭或断开,可以尝试重新连接。
  • RedisCommandTimeoutException:可以尝试增长命令的超时时间,或者查看Redis服务器是否有性能问题,如CPU使用过高,磁盘IO过高等。
  • RedisCommandInterruptedException:可以查看线程为何被停止,并尝试解决停止的原因。
  • RedisCommandExecutionException:查抄你的Redis命令是否正确,如键是否存在,类型是否匹配等。假如命令没有问题,则可能是Redis服务器的问题,需要查抄服务器的状况。
6. Lettuce vs 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。 7. 参考资料

Lettuce

  • 官方文档:Lettuce
  • GitHub:Lettuce GitHub
  • 深入相识Lettuce:Understanding Lettuce
  • Lettuce源码分析:Lettuce source code analysis
Jedis

  • 官方文档:Jedis
  • GitHub:Jedis GitHub
  • 深入相识Jedis:Understanding Jedis
  • Jedis源码分析:Jedis source code analysis
Redis

  • 官方文档:Redis
  • GitHub:Redis GitHub
  • Redis命令:Redis commands
  • Redis入门教程:Redis tutorial

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

曂沅仴駦

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表