返回顶部
首页 > 资讯 > 数据库 >Redis实战之Lettuce的使用技巧详解
  • 575
分享到

Redis实战之Lettuce的使用技巧详解

Redis Lettuce使用技巧Redis Lettuce使用Redis Lettuce 2022-12-23 10:12:06 575人浏览 薄情痞子
摘要

目录一、摘要二、Lettuce2.1、基本使用2.2、同步操作2.3、异步操作2.4、响应式编程2.5、发布和订阅2.6、客户端资源与参数配置2.7、线程池配置2.8、主从模式配置2.9、哨兵模式配置2.10、Clust

一、摘要

Lettuce 是 Redis 的一款高级 Java 客户端,与 Jedis 并列成为最热门的客户端之一,目前已成为 SpringBoot 2.0 版本默认的 redis 客户端。

Redis实战之Lettuce的使用技巧详解

相比老牌 Jedis,Lettuce 属于后起之秀,不仅功能丰富,而且提供了很多新的功能特性,比如异步操作、响应式编程等等,同时还解决了 Jedis 中线程安全的问题。

废话不多说了,如何使用呢?请看下文!

二、Lettuce

2.1、基本使用

首先,创建一个 Maven 项目,引入lettuce-core包,就可以使用了。

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

使用 lettuce 连接 redis,测试是否能正常联通!

publicclassLettuceMain{

publicstaticvoidmain(String[]args){
RedisURIredisUri=RedisURI.builder()
.withHost("127.0.0.1")
.withPort(6379)
.withPassword("111111")
.withTimeout(Duration.of(10,ChronoUnit.SECONDS))
.build();
RedisClientredisClient=RedisClient.create(redisUri);
StatefulRedisConnection<String,String>connection=redisClient.connect();
RedisCommands<String,String>commands=connection.sync();
System.out.println(commands.ping());
connection.close();
redisClient.shutdown();
}
}

2.2、同步操作

基本上只要是 Jedis 支持的同步命令操作,Lettuce 都支持。

下面,我们以同步操作字符串为例,Lettuce 的 api 操作如下!

publicclassLettuceSyncMain{

publicstaticvoidmain(String[]args){
RedisURIredisUri=RedisURI.builder()
.withHost("127.0.0.1").withPort(6379).withPassword("111111")
.withTimeout(Duration.of(10,ChronoUnit.SECONDS))
.build();
RedisClientredisClient=RedisClient.create(redisUri);
StatefulRedisConnection<String,String>connection=redisClient.connect();
//获取同步操作命令工具
RedisCommands<String,String>commands=connection.sync();

System.out.println("清空数据:"+commands.flushdb());
System.out.println("判断某个键是否存在:"+commands.exists("username"));
System.out.println("新增<'username','xmr'>的键值对:"+commands.set("username","xmr"));
System.out.println("新增<'passWord','password'>的键值对:"+commands.set("password","123"));
System.out.println("获取<'password'>键的值:"+commands.get("password"));
System.out.println("系统中所有的键如下:"+commands.keys("*"));
System.out.println("删除键password:"+commands.del("password"));
System.out.println("判断键password是否存在:"+commands.exists("password"));
System.out.println("设置键username的过期时间为5s:"+commands.expire("username",5L));
System.out.println("查看键username的剩余生存时间:"+commands.ttl("username"));
System.out.println("移除键username的生存时间:"+commands.persist("username"));
System.out.println("查看键username的剩余生存时间:"+commands.ttl("username"));
System.out.println("查看键username所存储的值的类型:"+commands.type("username"));

connection.close();
redisClient.shutdown();
}
}

2.3、异步操作

除此之外,Lettuce 还支持异步操作,将上面的操作改成异步处理,结果如下!

publicclassLettuceASyncMain{

publicstaticvoidmain(String[]args)throwsException{
RedisURIredisUri=RedisURI.builder()
.withHost("127.0.0.1").withPort(6379).withPassword("111111")
.withTimeout(Duration.of(10,ChronoUnit.SECONDS))
.build();
RedisClientredisClient=RedisClient.create(redisUri);
StatefulRedisConnection<String,String>connection=redisClient.connect();
//获取异步操作命令工具
RedisAsyncCommands<String,String>commands=connection.async();

System.out.println("清空数据:"+commands.flushdb().get());
System.out.println("判断某个键是否存在:"+commands.exists("username").get());
System.out.println("新增<'username','xmr'>的键值对:"+commands.set("username","xmr").get());
System.out.println("新增<'password','password'>的键值对:"+commands.set("password","123").get());
System.out.println("获取<'password'>键的值:"+commands.get("password").get());
System.out.println("系统中所有的键如下:"+commands.keys("*").get());
System.out.println("删除键password:"+commands.del("password").get());
System.out.println("判断键password是否存在:"+commands.exists("password").get());
System.out.println("设置键username的过期时间为5s:"+commands.expire("username",5L).get());
System.out.println("查看键username的剩余生存时间:"+commands.ttl("username").get());
System.out.println("移除键username的生存时间:"+commands.persist("username").get());
System.out.println("查看键username的剩余生存时间:"+commands.ttl("username").get());
System.out.println("查看键username所存储的值的类型:"+commands.type("username").get());

connection.close();
redisClient.shutdown();
}
}

2.4、响应式编程

Lettuce 除了支持异步编程以外,还支持响应式编程,Lettuce 引入的响应式编程框架Project Reactor,如果没有响应式编程经验可以先自行了解一下,访问地址https://projectreactor.io/。

响应式编程使用案例如下:

publicclassLettuceMain{

publicstaticvoidmain(String[]args)throwsException{
RedisURIredisUri=RedisURI.builder()
.withHost("127.0.0.1").withPort(6379).withPassword("111111")
.withTimeout(Duration.of(10,ChronoUnit.SECONDS))
.build();
RedisClientredisClient=RedisClient.create(redisUri);
StatefulRedisConnection<String,String>connection=redisClient.connect();
//获取响应式API操作命令工具
RedisReactiveCommands<String,String>commands=connection.reactive();

Mono<String>setc=commands.set("name","mayun");
System.out.println(setc.block());
Mono<String>getc=commands.get("name");
getc.subscribe(System.out::println);
Flux<String>keys=commands.keys("*");
keys.subscribe(System.out::println);

//开启一个事务,先把count设置为1,再将count自增1
commands.multi().doOnSuccess(r->{
commands.set("count","1").doOnNext(value->System.out.println("count1:"+value)).subscribe();
commands.incr("count").doOnNext(value->System.out.println("count2:"+value)).subscribe();
}).flatMap(s->commands.exec())
.doOnNext(transactionResult->System.out.println("transactionResult:"+transactionResult.wasDiscarded())).subscribe();

Thread.sleep(1000*5);
connection.close();
redisClient.shutdown();
}
}

2.5、发布和订阅

Lettuce 还支持 redis 的消息发布和订阅,具体实现案例如下:

publicclassLettuceReactiveMain1{

publicstaticvoidmain(String[]args)throwsException{
RedisURIredisUri=RedisURI.builder()
.withHost("127.0.0.1").withPort(6379).withPassword("111111")
.withTimeout(Duration.of(10,ChronoUnit.SECONDS))
.build();
RedisClientredisClient=RedisClient.create(redisUri);
//获取发布订阅操作命令工具
StatefulRedisPubSubConnection<String,String>pubsubConn=redisClient.connectPubSub();
pubsubConn.addListener(newRedisPubSubListener<String,String>(){
@Override
publicvoidunsubscribed(StrinGChannel,longcount){
System.out.println("[unsubscribed]"+channel);
}
@Override
publicvoidsubscribed(Stringchannel,longcount){
System.out.println("[subscribed]"+channel);
}
@Override
publicvoidpunsubscribed(Stringpattern,longcount){
System.out.println("[punsubscribed]"+pattern);
}
@Override
publicvoidpsubscribed(Stringpattern,longcount){
System.out.println("[psubscribed]"+pattern);
}
@Override
publicvoidmessage(Stringpattern,Stringchannel,Stringmessage){
System.out.println("[message]"+pattern+"->"+channel+"->"+message);
}
@Override
publicvoidmessage(Stringchannel,Stringmessage){
System.out.println("[message]"+channel+"->"+message);
}
});
RedisPubSubAsyncCommands<String,String>pubsubCmd=pubsubConn.async();
pubsubCmd.psubscribe("CH");
pubsubCmd.psubscribe("CH2");
pubsubCmd.unsubscribe("CH");

Thread.sleep(100*5);
pubsubConn.close();
redisClient.shutdown();
}
}

2.6、客户端资源与参数配置

Lettuce 客户端的通信框架集成了 Netty 的非阻塞 IO 操作,客户端资源的设置与 Lettuce 的性能、并发和事件处理紧密相关,如果不是特别熟悉客户端参数配置,不建议在没有经验的前提下凭直觉修改默认值,保持默认配置就行。

非集群环境下,具体的配置案例如下:

publicclassLettuceMain{

publicstaticvoidmain(String[]args)throwsException{
ClientResourcesresources=DefaultClientResources.builder()
.ioThreadPoolSize(4)//I/O线程数
.computationThreadPoolSize(4)//任务线程数
.build();
RedisURIredisUri=RedisURI.builder()
.withHost("127.0.0.1").withPort(6379).withPassword("111111")
.withTimeout(Duration.of(10,ChronoUnit.SECONDS))
.build();
ClientOptionsoptions=ClientOptions.builder()
.autoReconnect(true)//是否自动重连
.pingBeforeActivateConnection(true)//连接激活之前是否执行PING命令
.build();
RedisClientclient=RedisClient.create(resources,redisUri);
client.setOptions(options);
StatefulRedisConnection<String,String>connection=client.connect();
RedisCommands<String,String>commands=connection.sync();
commands.set("name","关羽");
System.out.println(commands.get("name"));

connection.close();
client.shutdown();
resources.shutdown();
}
}

集群环境下,具体的配置案例如下:

publicclassLettuceMain{

publicstaticvoidmain(String[]args)throwsException{
ClientResourcesresources=DefaultClientResources.builder()
.ioThreadPoolSize(4)//I/O线程数
.computationThreadPoolSize(4)//任务线程数
.build();
RedisURIredisUri=RedisURI.builder()
.withHost("127.0.0.1").withPort(6379).withPassword("111111")
.withTimeout(Duration.of(10,ChronoUnit.SECONDS))
.build();
ClusterClientOptionsoptions=ClusterClientOptions.builder()
.autoReconnect(true)//是否自动重连
.pingBeforeActivateConnection(true)//连接激活之前是否执行PING命令
.validateClusternodeMembership(true)//是否校验集群节点的成员关系
.build();
RedisClusterClientclient=RedisClusterClient.create(resources,redisUri);
client.setOptions(options);
StatefulRedisClusterConnection<String,String>connection=client.connect();
RedisAdvancedClusterCommands<String,String>commands=connection.sync();
commands.set("name","张飞");
System.out.println(commands.get("name"));

connection.close();
client.shutdown();
resources.shutdown();
}
}

2.7、线程池配置

Lettuce 连接设计的时候,就是线程安全的,所以一个连接可以被多个线程共享,同时 lettuce 连接默认是自动重连的,使用单连接基本可以满足业务需求,大多数情况下不需要配置连接池,多连接并不会给操作带来性能上的提升。

但在某些特殊场景下,比如事物操作,使用连接池会是一个比较好的方案,那么如何配置线程池呢?

publicclassLettuceMain{

publicstaticvoidmain(String[]args)throwsException{
RedisURIredisUri=RedisURI.builder()
.withHost("127.0.0.1")
.withPort(6379)
.withPassword("111111")
.withTimeout(Duration.of(10,ChronoUnit.SECONDS))
.build();
RedisClientclient=RedisClient.create(redisUri);
//连接池配置
GenericObjectPoolConfigpoolConfig=newGenericObjectPoolConfig();
poolConfig.setMaxIdle(2);

GenericObjectPool<StatefulRedisConnection<String,String>>pool=ConnectionPoolSupport.createGenericObjectPool(client::connect,poolConfig);
StatefulRedisConnection<String,String>connection=pool.borrowObject();
RedisCommands<String,String>commands=connection.sync();
commands.set("name","张飞");
System.out.println(commands.get("name"));

connection.close();
pool.close();
client.shutdown();
}
}

2.8、主从模式配置

redis 一般采用主从复制模式,搭建高可用架构,简单的说就一个主节点,多个从节点,自动从主节点同步最新数据。

Lettuce 支持自动发现主从模式下的节点信息,然后保存到本地,具体配置如下:

publicclassLettuceMain{

publicstaticvoidmain(String[]args)throwsException{
//这里只需要配置一个节点的连接信息,不一定需要是主节点的信息,从节点也可以;可以自动发现主从节点
RedisURIuri=RedisURI.builder().withHost("192.168.31.111").withPort(6379).withPassword("123456").build();
RedisClientclient=RedisClient.create(uri);
StatefulRedisMasterReplicaConnection<String,String>connection=MasterReplica.connect(client,StringCodec.UTF8,uri);
//从节点读取数据
connection.setReadFrom(ReadFrom.REPLICA);

RedisCommands<String,String>commands=connection.sync();
commands.set("name","张飞");
System.out.println(commands.get("name"));

connection.close();
client.shutdown();
}
}

当然我们也可以手动指定集群节点来加载,具体配置如下:

publicclassLettuceMain{

publicstaticvoidmain(String[]args)throwsException{
//集群节点
List<RedisURI>uris=newArrayList();
uris.add(RedisURI.builder().withHost("192.168.31.111").withPort(6379).withPassword("111111").build());
uris.add(RedisURI.builder().withHost("192.168.31.112").withPort(6379).withPassword("111111").build());
uris.add(RedisURI.builder().withHost("192.168.31.113").withPort(6379).withPassword("111111").build());

RedisClientclient=RedisClient.create();
StatefulRedisMasterReplicaConnection<String,String>connection=MasterReplica.connect(client,StringCodec.UTF8,uris);
//从节点读取数据
connection.setReadFrom(ReadFrom.REPLICA);

RedisCommands<String,String>commands=connection.sync();
commands.set("name","张飞");
System.out.println(commands.get("name"));

connection.close();
client.shutdown();
}
}

2.9、哨兵模式配置

哨兵模式,也是 redis 实现服务高可用的一大亮点,具体配置实现如下:

publicclassLettuceMain{

publicstaticvoidmain(String[]args)throwsException{
//集群节点
List<RedisURI>uris=newArrayList();
uris.add(RedisURI.builder().withSentinel("192.168.31.111",26379).withSentinelMasterId("mymaster").withPassword("123456").build());
uris.add(RedisURI.builder().withSentinel("192.168.31.112",26379).withSentinelMasterId("mymaster").withPassword("123456").build());
uris.add(RedisURI.builder().withSentinel("192.168.31.113",26379).withSentinelMasterId("mymaster").withPassword("123456").build());

RedisClientclient=RedisClient.create();
StatefulRedisMasterReplicaConnection<String,String>connection=MasterReplica.connect(client,StringCodec.UTF8,uris);
//从节点读取数据
connection.setReadFrom(ReadFrom.REPLICA);

RedisCommands<String,String>commands=connection.sync();
commands.set("name","赵云");
System.out.println(commands.get("name"));

connection.close();
client.shutdown();
}
}

2.10、Cluster 集群模式配置

Cluster 集群模式,是之后推出的一种高可用的架构模型,主要是采用分片方式来存储数据,具体配置如下:

publicclassLettuceReactiveMain4{

publicstaticvoidmain(String[]args)throwsException{
Set<RedisURI>uris=newHashSet<>();
uris.add(RedisURI.builder().withHost("192.168.31.111").withPort(7000).withPassword("123456").build());
uris.add(RedisURI.builder().withHost("192.168.31.112").withPort(7000).withPassword("123456").build());
uris.add(RedisURI.builder().withHost("192.168.31.113").withPort(7000).withPassword("123456").build());
uris.add(RedisURI.builder().withHost("192.168.31.114").withPort(7000).withPassword("123456").build());
uris.add(RedisURI.builder().withHost("192.168.31.115").withPort(7000).withPassword("123456").build());
uris.add(RedisURI.builder().withHost("192.168.31.116").withPort(7001).withPassword("123456").build());

RedisClusterClientclient=RedisClusterClient.create(uris);
StatefulRedisClusterConnection<String,String>connection=client.connect();
RedisAdvancedClusterCommands<String,String>commands=connection.sync();
commands.set("name","关羽");
System.out.println(commands.get("name"));

//选择从节点,只读
NodeSelection<String,String>replicas=commands.replicas();
NodeSelectionCommands<String,String>nodeSelectionCommands=replicas.commands();
Executions<List<String>>keys=nodeSelectionCommands.keys("*");
keys.forEach(key->System.out.println(key));

connection.close();
client.shutdown();
}
}

三、小结

Lettuce 相比老牌的 Jedis 客户端,功能更加强大,不仅解决了线程安全的问题,还支持异步和响应式编程,支持集群,Sentinel,管道和编码器等等功能。

以上介绍的可能只是冰山一角,如果想要了解更多的信息,可以访问它的官网地址:Https://lettuce.io/

到此这篇关于Redis实战之Lettuce的使用技巧详解的文章就介绍到这了,更多相关Redis Lettuce内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

您可能感兴趣的文档:

--结束END--

本文标题: Redis实战之Lettuce的使用技巧详解

本文链接: https://lsjlt.com/news/175624.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Redis实战之Lettuce的使用技巧详解
    目录一、摘要二、Lettuce2.1、基本使用2.2、同步操作2.3、异步操作2.4、响应式编程2.5、发布和订阅2.6、客户端资源与参数配置2.7、线程池配置2.8、主从模式配置2.9、哨兵模式配置2.10、Clust...
    99+
    2022-12-23
    Redis Lettuce使用技巧 Redis Lettuce使用 Redis Lettuce
  • Redis实战之Jedis使用技巧详解
    目录一、摘要二、Jedis2.1、基本使用2.2、连接池2.3、连接池配置2.4、字符串常用 API 操作2.5、哈希常用 API 操作2.6、列表常用 API 操作2.7、集合常用 API 操作2.8、有序集合常用 A...
    99+
    2022-12-22
    Redis Jedis使用技巧 Redis Jedis使用 Redis Jedis
  • Spring Cloud实战技巧之使用随机端口
    前言在Spring Cloud构建微服务架构中,我们经常会需要启动多个实例的情况来测试注册中心、配置中心等基础设施的高可用,也会用来测试客户端负载均衡的调用等。但是,我们一个应用只能有一个端口号,这就使得在本机测试的时候,不得不为同一个服务...
    99+
    2023-05-31
    springcloud 随机端口
  • Python必备技巧之函数的使用详解
    目录1.如何用函数2.默认参数陷阱2.1针对可变数据类型,不可变不受影响3.名称空间和作用域4.闭包函数5.函数的参数5.1定义阶段5.2调用阶段6.装饰器:闭包函数的应用6.1装饰...
    99+
    2024-04-02
  • java实战小技巧之字符串与容器互转详解
    目录前言I. 字符串转列表1. jdk支持方式2. guava方式3. apache-commonsII. 列表转字符串1. StringBuilder2. String.join3...
    99+
    2024-04-02
  • Git操作规范之tag的使用技巧详解
    目录常用分支masterdevelopreleasehotfix使用注意tag规范打tag场景tag命名规范版本类型说明版本号设置规范场景举例新需求修复bug重大版本更新特殊情况常用...
    99+
    2024-04-02
  • springboot redis使用lettuce配置多数据源的实现
    目前项目上需要连接两个redis数据源,一个redis数据源是单机模式,一个redis数据源是分片集群模式,这里将具体配置列一下。 项目用的springboot版本为 &...
    99+
    2024-04-02
  • 高并发技巧之Redis和本地缓存使用技巧分享
    目录三种缓存的使用场景Redis的使用场景和局限性LoadingCache的使用场景和局限性ReloadableCache的使用场景和局限性小结小技巧缓存使用的简单介绍LoadingCache的使用reloadableC...
    99+
    2024-04-02
  • Python实战之unittest使用详
    一 unittest是什么?unittest是python内置的单元测试框架,具备编写用例、组织用例、执行用例、输出报告等自动化框架的条件。 使用unittest前需要了解该框架的五个概念: 即test case,test suite,te...
    99+
    2023-01-31
    实战 Python unittest
  • MyBatis之Mapper详解及常用技巧
    select先看一个简单的案例:<select id="selectPerson" parameterType="int" resultType="hashma...
    99+
    2024-04-02
  • Redis 使用的 10 个小技巧
    Redis 在当前的技术社区里是非常热门的。从来自 Antirez 一个小小的个人项目到成为内存数据存储行业的标准,Redis已经走过了很长的一段路。 随之而来的一系列最佳实践,使得大多数人可以正确地使用 Redis。 下面我们将...
    99+
    2014-08-05
    Redis 使用的 10 个小技巧
  • redis数据库的使用技巧
    今天就跟大家聊聊有关redis数据库的使用技巧,相信大部分人都还不知道这些技巧,因此给大家总结了以下内容,希望大家阅读完后可以有所收获。1、停止使用 KEYS *Okay,以挑战这个命令开始这篇文章,或许并...
    99+
    2024-04-02
  • winxp技巧使用方法及特殊之处详解
    1.在记事本中自动记录文件的打开时间 在记事本中,我们可以记录每次打开某个文本文件的时间,方法为:在该文件的第一行输入“.LOG”(注意:必须大写!),然后换行开始正文。这样在每次打开了该文件之后...
    99+
    2023-05-26
    winxp技巧 windowsxp使用技巧 使用 winxp 技巧 方法
  • vue3name属性的使用技巧详解
    目录引言使用步骤引言 如果你在 vue3 开发中使用了 <script setup> 语法的话,对于组件的 name 属性,需要做一番额外的处理。 对于 vue@3.2....
    99+
    2024-04-02
  • Python字典使用技巧详解
    目录1. 引言2. 使用union操作合并字典3. 使用解包操作合并字典4. 使用字典生成式5. 字典中key-value互换6. 列表转为字典7. 字典按照value来排...
    99+
    2022-11-16
    Python字典用法 Python字典
  • 详解go语言json的使用技巧
    本文整理了一部分我们平时在项目中经常遇到的关于go语言JSON数据与结构体之间相互转换的问题及解决办法。 基本的序列化 首先我们来看一下Go语言中json.Marshal()...
    99+
    2022-06-07
    json的使用 JSON GO 技巧
  • Redis正确使用的十个技巧
    Redis 在当前的技术社区里是非常热门的。从来自 Antirez 一个小小的个人项目到成为内存数据存储行业的标准,Redis已经走过了很长的一段路。 1、停止使用 KEYS * Okay,以挑战这个命令开...
    99+
    2022-06-04
    正确 技巧 Redis
  • Pytorch使用技巧之Dataloader中的collate_fn参数详析
    以MNIST为例 from torchvision import datasets mnist = datasets.MNIST(root='./data/', train=True...
    99+
    2024-04-02
  • 详解使用PHP开发直播功能的实用技巧
    随着互联网的不断发展,直播功能也越来越受到人们的关注和青睐。在这样一个直播风潮的时代,需要一款稳定可靠的直播平台。而PHP作为一种强大的服务器端开发语言,可以用于创建高度交互性的应用程序,能够为直播平台的开发提供利器,本文就为大家详细介绍使...
    99+
    2023-05-22
    直播 技巧 PHP
  • Sails.js 实战技巧:Node.js 后端开发的进阶之法
    使用缓存(如 Redis)来存储经常访问的数据。 优化数据库查询,使用索引和适当的联接。 利用 Sails.js 的水线 ORM 来执行高效的查询。 压缩和 minify 前端资产以减少加载时间。 提升安全性 使用 Cross-Si...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作