掌秋使 手游攻略 手游评测 初看Redis客户端Lettuce:真好吃

初看Redis客户端Lettuce:真好吃

时间:2024-10-06 15:11:51 来源:其他 浏览:0

在一次技术讨论会上,大家讨论Redis的Java客户端哪个更好。我立即大喊‘杰迪斯,是的! '

“Jedis是官方客户端,简单易用,所有公司都用它作为中间件,除了Jedis还有谁能打吗?”我直接把王渣扔了。

刚学Spring的小张很不满:“SpringDataRedis都用RedisTemplate!Jedis?不存在。”

“秀儿坐下,SpringDataRedis是基于Jedis进行封装的。”旁边,李大哥喝了一口新开的快乐水,嘴角微微扬起,露出一丝不屑。

“现在很多人都用生菜,你知道吗?”老王推了推眼镜,平静的说道,然后缓缓打开了镜片后面的心灵之窗,用关爱的目光低头看着我们这些新人。

莴苣?莴苣?一头雾水,我赶紧打开Redis官网的客户端列表。发现Java语言官方推荐的实现有三种:Jedis、Lettuce和Redission。

生菜是什么客户?从来没有听说过。但我发现它的官方介绍是最长的:

用于线程安全同步、异步和反应式使用的高级Redis 客户端。支持集群、哨兵、管道和编解码器。

我赶紧查字典翻译:

高级客户端线程安全支持同步、异步和反应式API,支持集群、哨兵、管道和编解码器。老王摆摆手,示意我把字典收起来,慢慢地介绍。

1.1 高级客户端

“主人,请翻译官翻译一下,什么(嘟——)叫(嘟——)高级客户端?”

“高级客户端,高级,就是高级!新的可以立即使用,不需要担心任何实现细节,直接接业务逻辑,直接跳转。”

1.2 线程安全

这是与绝地武士的主要区别之一。

Jedis的连接实例是线程不安全的,所以需要维护一个连接池。每个线程在需要时从连接池中取出连接实例,并在完成操作或遇到异常后返回该实例。当连接数量随着业务不断增长时,物理连接的消耗也将成为性能和稳定性的潜在风险点。

Lettuce使用Netty作为通信层组件。它的连接实例是线程安全的,当满足条件时,它可以访问操作系统的原生调用epoll、kqueue等以获得性能提升。

我们知道,虽然一个Redis服务器实例可以同时连接多个客户端来发送和接收命令,但每个实例在执行命令时都是单线程的。

这意味着,如果应用程序能够通过多线程+单连接的方式操作Redis,就可以减少Redis服务器上的连接总数,并且在多个应用程序共享同一台Redis服务器时可以获得更好的稳定性和性能。对于应用程序来说,也减少了维护多个连接实例的资源消耗。

1.3 支持同步、异步和反应式API

Lettuce从一开始就是按照非阻塞IO来设计的。它是一个纯异步客户端,全面支持异步和反应式API。

即使是同步命令,底层通信过程仍然是异步模型,只是通过阻塞调用线程来模拟同步效果。

1.4 支持集群、哨兵、管道和编解码器

“这些功能都是标准的,Lettuce是高级客户端!高级,你明白吗?”老王说完这句话,兴奋地用手指着桌子,但似乎并不想多做介绍。我默默记下好好学习的笔记。

(项目使用过程中,管道机制比Jedis稍微抽象一些,下面给出使用过程中遇到的坑和解决方案。)

1.5 Spring中的使用

初看Redis客户端Lettuce:真好吃

除了官方对Redis的介绍之外,我们还可以发现,当Spring Data Redis升级到2.0时,Lettuce也升级到了5.0。事实上,Lettuce从SpringDataRedis 1.6开始就已经正式集成;而SpringSessionDataRedis直接使用Lettuce作为默认的Redis客户端,可见其成熟性和稳定性。

Jedis 是众所周知的,甚至是事实上的标准驱动程序。它推出较早(2010年9月发布1.0.0版,2011年3月发布Lettuce 1.0.0),其API简单易用。诸如对Redis新功能的最快支持等特性是密不可分的。

2. Jedis和Lettuce的主要区别是什么?

说了这么多,Lettuce 和老客户Jedis 的主要区别是什么?我们可以看一下Spring Data Redis帮助文档中给出的对比表:

注:其中 X 标记的是支持.

经过比较可以发现:

支持Jedis支持的Lettuce; Jedis不支持的生菜也支持!春天生菜的使用越来越多也就不足为奇了。

3. 生菜初体验

3.1 快速入门

如果即使是最简单的示例也令人困惑,那么该库就不会流行。 Lettuce的快速启动速度确实很快:

一个。引入maven依赖(其他依赖类似,具体参见文末参考资料)

依赖项groupIdio.lettuce/groupId artifactIdlettuce-core/artifactId version5.3.6.RELEASE/version/dependencyb。填写Redis地址,连接,执行,关闭。完美的!

导入io.lettuce.core.*; //语法: redis://[密码@]主机[:端口][/databaseNumber]//语法: redis://[用户名:密码@]主机[:端口][/数据库编号]RedisClient redisClient=RedisClient. create('redis://password@localhost:6379/0');StatefulRedisConnectionString, 字符串连接=redisClient.connect();RedisCommandsString, 字符串syncCommands=connection.sync(); syncCommands.set('key', '你好,Redis!' ); connection.close();redisClient.shutdown();3.2 是否支持集群模式?支持!

Redis Cluster是官方提供的Redis Sharding解决方案。大家应该都很熟悉了,我就不多介绍了。官方文档请参考Redis Cluster 101。

要将Lettuce连接到Redis集群,只需将上面的客户端代码逐行更改即可:

//语法: redis://[password@]host[:port]//语法: redis://[username:password@]host[:port]RedisClusterClient redisClient=RedisClusterClient.create('redis://password@localhost:7379'); 3.3 支持是否高可靠?支持!

Redis Sentinel是官方提供的高可靠性解决方案。 Sentinel可以在实例发生故障时自动切换到从节点继续提供服务。官方文档请参考Redis Sentinel文档。

只需替换客户端的创建方式即可:

//语法: redis-sentinel://[密码@]主机[:port][,host2[:port2]][/databaseNumber]#sentinelMasterIdRedisClient redisClient=RedisClient.create('redis-sentinel: //localhost:26379,localhost:26380/0#my master' ) ;3.4 集群下是否支持pipeline?支持!

Jedis虽然有pipeline命令,但是无法支持Redis Cluster。一般情况下,在批量执行管道之前,需要合并每个key所在的slot和实例。

尽管Lettuce声称支持管道,但它并没有直接看到管道API。这是怎么回事?

3.4.1 实现 pipeline

使用AsyncCommands和flushCommands来实现管道。阅读官方文档后我们可以知道,Lettuce的同步和异步命令实际上共享同一个连接实例,底层使用管道来发送/接收命令。

区别在于:

通过connection.sync()方法获得的同步命令对象,每次操作都会立即通过TCP连接发送命令;通过connection.async()获取的异步命令对象会获取RedisFuture吗?执行操作后。当满足某些条件时仅在某些情况下分批发送。由此,我们可以通过异步命令+手动批量推送的方式来实现管道。我们看一下官方的例子:

StatefulRedisConnectionString,字符串连接=client.connect();RedisAsyncCommandsString,字符串命令=connection.async(); //禁用自动刷新命令。setAutoFlushCommands(false); //执行一系列独立的调用ListRedisFuture? futures=Lists.newArrayList() ;for (int i=0; i 次迭代; i++) {futures.add(commands.set('key-' + i, 'value-' + i));futures.add(commands .expire('key-' + i, 3600));} //将所有命令写入传输层commands.flushCommands(); //同步example: 等待所有futures 完成boolean result=LettuceFutures.awaitAll(5, TimeUnit.SECONDS,futures.toArray(new RedisFuture[ futures.size()])); //后来连接.close();

3.4.2 这么做有没有问题?

初看Redis客户端Lettuce:真好吃

乍一看很完美,但实际上存在陷阱:

设置setAutoFlushCommands(false)后,你会发现sync()方法调用的同步命令没有返回!这是为什么呢?我们看一下官方文档:

Lettuce 是一个非阻塞异步客户端。它提供了一个同步API 来实现基于每个线程的阻塞行为,以创建等待(同步)命令响应.第一个请求返回后,第一个线程的程序流程将继续,而第二个请求则继续执行。由Redis处理并在某个时间点返回

sync和async的底层实现是一样的,只不过sync是通过阻塞调用线程来模拟同步操作。而setAutoFlushCommands从源码中可以发现它作用于连接对象,所以这个操作对同步和异步命令对象都生效。

因此,只要在一个线程中将自动刷新命令设置为false,就会影响使用该连接实例的所有其他线程。

/*** 用于Redis 连接的异步且线程安全的API。** @param K 键类型。* @param V 值类型。* @author Will Glozer* @author Mark Paluch*/public 抽象类AbstractRedisAsyncCommandsK,V 实现RedisHashAsyncCommandsK、V、RedisKeyAsyncCommandsK、V、RedisStringAsyncCommandsK、V、RedisListAsyncCommandsK、V、RedisSetAsyncCommandsK、V、RedisSortedSetAsyncCommandsK、V、RedisScriptingAsyncCommandsK、V、RedisServerAsyncCommandsK、V、Redis HLLAsyncCommandsK、V、BaseRedisAsyncCommandsK、V、RedisTransactionalAsync命令K、V、RedisGeoAsyncCommandsK、V、RedisClusterAsyncCommandsK , V { @Override public void setAutoFlushCommands(boolean autoFlush) { connection.setAutoFlushCommands(autoFlush); }相应的,如果多个线程调用async()获取异步命令集,并在自己的业务逻辑完成后调用flushCommands(),那么仍然有其他线程追加的异步命令会被强制flush,逻辑上不执行的命令会被强制flush。属于整个批次的将被分成多个副本并发送。

虽然不影响结果的准确性,但是如果线程之间互相干扰,分散了彼此发送的命令,那么性能的提升会很不稳定。

我们自然会想:每一个批处理命令都会创建一个连接,然后……这不就和Jedis一样依赖连接池吗?

想起老王镜头后那双撕心裂肺的眼神,我决定再深入挖掘一下。果然,再次仔细阅读文档后,我发现了另一个好东西:Batch Execution。

3.4.3 Batch Execution

既然flushCommands会对连接产生全局影响,那么将flush限制在线程级别还不够吗?我从文档中找到了示例官方示例。

回顾上一篇文章,Lettuce 是一个高级客户端。看完文档,发现确实很高级。只需要定义一个接口(让人想起MyBatis的Mapper接口)。以下是项目中使用的示例:

/** * 定义将使用的批处理命令*/@BatchSize(100) public interface RedisBatchQuery extends Commands, BatchExecutor { RedisFuturebyte[] get(byte[] key); RedisFutureSetbyte[] smembers(byte[] key); RedisFutureListbyte[ ] lrange(byte[] key, 长开始, 长结束); RedisFutureMapbyte[], byte[] hgetall(byte[] key);} 调用时,执行以下操作:

//创建客户端RedisClusterClient client=RedisClusterClient.create(DefaultClientResources.create(), 'redis://' + 地址); //工厂实例保存在服务中并且仅创建一次。第二个参数表示使用byte[]编码和解码的键和值。 RedisCommandFactory 工厂=new RedisCommandFactory(connect, Arrays.asList(ByteArrayCodec.INSTANCE, ByteArrayCodec.INSTANCE)); //在哪里使用,创建一个查询实例代理类来调用命令,最后刷入命令ListRedisFuture? futures=new ArrayList();RedisBatchQuery batchQuery=factory.getCommands(RedisBatchQuery.class);for (RedisMetaGroup redisMetaGroup : redisMetaGroups) { //业务逻辑,循环调用多个key,并将结果保存到futures 结果中,appendCommand(redisMetaGroup, futures,batchQuery);} //异步命令调用完成后,进行flush批量执行。然后命令才会发送到Redis服务器batchQuery.flush();就是这么简单。

此时会以线程粒度进行批量控制,当调用flush或者达到@BatchSize配置的缓存命令数量时进行批量操作。对于连接实例,不需要设置自动刷新命令,保持默认true即可,不会影响其他线程。

ps:作为一个优秀且严谨的人,你肯定会认为如果单个命令执行时间很长或者有人放了BLPOP之类的命令,肯定会有影响。这个话题官方文档中也有介绍,可以考虑使用连接池来处理。

3.5还能更强吗?

当然,Lettuce支持的不仅仅是上面提到的简单功能,还有这些值得一试的功能:

3.5.1 读写分离

我们知道Redis实例支持主从部署。从实例与主实例异步同步数据,并在主实例出现故障时使用Redis Sentinel进行主从切换。

当应用对数据一致性不敏感且需要较大吞吐量时,可以考虑主从读写分离方式。 Lettuce可以通过设置StatefulRedisClusterConnection的readFrom配置来调整:

3.5.2 配置自动更新集群拓扑

当使用 Redis Cluster 时,服务端发生了扩容怎么办?

Lettuce已经考虑到了这个——,通过RedisClusterClient#setOptions方法传入ClusterClientOptions对象来配置相关参数(所有配置见文末参考链接)。

在ClusterClientOptions 中

TopologyRefreshOptions的常用配置如下:

初看Redis客户端Lettuce:真好吃

3.5.3 连接池

虽然Lettuce的线程安全单连接实例已经具有非常好的性能,但是不排除一些大型业务需要使用线程池来提高吞吐量。此外,事务操作需要独占连接。

Lettuce基于Apache Common-pool2组件提供连接池能力(以下是RedisCluster官方的客户端线程池使用示例):

RedisClusterClient clusterClient=RedisClusterClient.create(RedisURI.create(主机、端口)); GenericObjectPoolStatefulRedisClusterConnectionString, 字符串池=ConnectionPoolSupport .createGenericObjectPool(() - clusterClient.connect(), new GenericObjectPoolConfig()); //执行worktry (StatefulRedisClusterConnectionString, String connection=pool.borrowObject()) { connection.sync().set('key', 'value'); connection.sync().blpop(10, 'list');} //terminationpool.close();clusterClient .shutdown();这里需要说明的是:createGenericObjectPool创建一个连接池,并将wrapConnections参数默认设置为true。此时,会重载借出对象的close方法,通过动态代理返回连接;如果设置为false,close 方法将关闭连接。

Lettuce还支持异步连接池(从连接池获取连接是一个异步操作)。详细内容请参考文章末尾的链接。功能很多,无法一一列举。你可以在官方文档中找到说明和示例,值得一读。

4. 使用总结

与Jedis相比,Lettuce使用起来更加方便快捷,并且抽象程度较高。并且通过线程安全的连接,减少了系统的连接数量,提高了系统的稳定性。

对于高级玩家,Lettuce还提供了很多配置和接口,方便性能优化和深度业务定制场景。

另外不得不说的是,Lettuce的官方文档非常全面、详细,这是非常难得的。社区比较活跃,Committer 会积极回答各种问题,这使得很多问题可以自己解决。

相比之下,Jedis 的文档、维护和更新都比较慢。 JedisCluster pipeline 的PR 四年前(2021 年2 月)尚未合并。

参考

其中两个 GitHub 的 issue 含金量很高,强烈推荐一读!

1.生菜快速入门:https://lettuce.io

2.Redis Java 客户端

3.生菜官网:https://lettuce.io

4.SpringDataRedis参考文档

5.关于流水线的问题

6.为什么Spring Session Redis默认使用Lettuce作为Redis客户端

7.Cluster-specific options: https://lettuce.io 8. Lettuce 连接池 9.客户端配置: https://lettuce.io/core/release

用户评论

毒舌妖后

作为游戏开发者,我在项目初期就考虑了Redis客户端Lettuce,从初步接触到现在已经离不开它。

    有16位网友表示赞同!

花海

Lettuce让我的数据库交互效率提升了一个档次!真的是物超所值。

    有9位网友表示赞同!

岁岁年年

从安装到使用都超级方便,完美适配了我们的游戏开发流程,非常推荐给需要高可用性的项目。

    有5位网友表示赞同!

瑾澜

相比之前的Redis客户端,Lettuce的性能简直惊人。不论是读写速度还是内存占用都低得多。

    有5位网友表示赞同!

早不爱了

尤其是对于并发请求处理能力上,Lettuce几乎能无缝应对我们游戏服务器的大流量挑战。

    有9位网友表示赞同!

志平

Lettuce在处理复杂场景时显得游刃有余,优化了我们的游戏服务架构和用户体验。

    有16位网友表示赞同!

虚伪了的真心

开始尝试Lettuce有些犹豫,但现在看真是我的眼光毒辣啊。真的很香!

    有17位网友表示赞同!

孤岛晴空

通过使用Lettuce,我们节省了大量的时间在调优数据库方面,精力可以花在更有趣的游戏内容上。

    有11位网友表示赞同!

良人凉人

游戏性能提升了不止一个台阶,得益于Lettuce带来的高效和稳定的网络连接管理。

    有6位网友表示赞同!

孤单*无名指

Lettuce稳定性极高,在处理高并发流量时完全没有出现过错误或延迟问题,这使我们充满信心。

    有20位网友表示赞同!

北染陌人

我被Redis的高性能吸引了,但Lettuce不仅提供了高性能,还带来了便利性和简洁性。

    有7位网友表示赞同!

心亡则人忘

Lettuce是游戏开发中的强大武器,特别是在需要快速响应和数据高效管理的游戏环境中。

    有16位网友表示赞同!

杰克

从一开始对新工具抱有抵触到如今成为忠实用户,Lettuce改变了我对 Redis 客户端的全部看法。

    有11位网友表示赞同!

病态的妖孽

对于游戏服务器的优化来说,选择Lettuce是最正确的决定。简单、高效、稳定。

    有10位网友表示赞同!

此生一诺

在尝试过很多其他Redis客户端之后,Lettuce让我们团队真正体验到了Redis带来的便利性和强大功能。

    有5位网友表示赞同!

箜篌引

不夸张地说,Lettuce是我最满意的游戏开发决策之一。它极大地提高了我们服务器的性能表现。

    有6位网友表示赞同!

浅巷°

Lettuce不仅增加了我们的开发效率,而且还稳定地维护了玩家体验,这在竞争激烈的市场中至关重要。

    有6位网友表示赞同!

安陌醉生

对于一个需要深度集成数据库处理的游戏项目来说,Lettuce简直是无价之宝。

    有5位网友表示赞同!

你与清晨阳光

自从用上了Lettuce,我们团队的技能提升和游戏性能优化都得到了显著改善。真香!

    有9位网友表示赞同!

冷眼旁观i

Lettuce不仅让我们的游戏数据管理更高效,还减少了错误发生的机会,让游戏体验更加流畅。

    有19位网友表示赞同!

苏莫晨

在快节奏的游戏开发中找到这样一颗高性能、易用又稳定的Redis客户端,就像找到了宝藏。

    有13位网友表示赞同!

你很爱吃凉皮

对于任何游戏开发者而言,Lettuce是一个不容错过的选择。无论是功能强大还是性能惊人,都能满足你的需要。

    有13位网友表示赞同!

标题:初看Redis客户端Lettuce:真好吃
链接:https://www.zhangqiushi.com/news/sypc/15142.html
版权:文章转载自网络,如有侵权,请联系删除!
资讯推荐
更多
绯红之境兑换码最新2021 礼包兑换码大全

绯红之境兑换码最新2021 礼包兑换码大全[多图],绯红之境兑换码怎么领取?绯红之境兑换码有哪些?绯红之境在今日

2024-10-06
妄想山海怎么加好友 加好友方法大全

妄想山海怎么加好友 加好友方法大全[多图],妄想山海添加好友功能在哪里?妄想山海添加好友的方法是什么?好友添

2024-10-06
三国群英传7霸王再临攻略 霸王再临攻略技巧开启方法

三国群英传7霸王再临攻略 霸王再临攻略技巧开启方法[多图],三国群英传7霸王再临怎么玩?三国群英传7霸王再临

2024-10-06
江南百景图又见桃花村钓鱼位置在哪?又见桃花村钓鱼攻略

江南百景图又见桃花村钓鱼位置在哪?又见桃花村钓鱼攻略[多图],江南百景图又见桃花村钓鱼怎么钓?又见桃花村钓

2024-10-06