Redis Client Lettuce 5 GA发布

经过13个月的开发阶段和208张已解决的故障单,我很高兴宣布Lettuce 5.0全面上市。 这是一个主要发行版,带有一些重大更改,新的有趣功能以及Java 9兼容性。

从Maven Central获取发布

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

或从GitHub下载发行包 。

生菜5引入了动态的Redis命令API。 此编程模型使您可以声明命令方法并根据需要调用命令并支持Redis模块,而无需等待Lettuce支持新命令。

如果本地依赖项可用,则莴苣在Linux各自的macOS系统上默认为本地传输(epoll,kqueue)。
生菜5带来了重大变化。 它删除了过时的接口RedisConnection和RedisAsyncConnection以及它们分离的接口,从而支持StatefulRedisConnection和RedisCommands等。

重大更改:

  1. 我们将工件坐标从biz.paluch.redis:lettuce移到io.lettuce:lettuce-core
  2. 我们将包从biz.paluch.redis重定位到io.lettuce.core。 通过将导入中的旧软件包名称替换为新软件包名称,可以轻松实现迁移路径。
  3. 该文档已从http://redis.paluch.biz移至https://lettuce.io 。
  4. 删除了番石榴。
  5. 我们删除了一些不推荐使用的方法,有关详细信息,请参见下文。

生菜只需要netty 4.1 (不再支持netty 4.0)和Project Reactor 3.1 ,这使我们有了下一个变化:

通过使用Project Reactor类型MonoFlux而不是RxJava 1和Observable ,反应式API基于反应式流。
如果您的代码中需要RxJava的SingleObservable ,则在rxjava-reactive-streams使用发布者适配器来适应MonoFlux

此版本引入了随常规工件一起提供的新参考指南。
该参考指南绑定到特定版本,并且不会随着时间的推移而更改,例如Wiki。

  • 参考文档: https : //lettuce.io/core/release/reference/ 。
  • JavaDoc文档: https : //lettuce.io/core/release/api/ 。
<dependency><groupId>io.lettuce</groupId><artifactId>lettuce-core</artifactId><version>5.0.0.RELEASE</version>
</dependency>

您可以找到完整的更改日志,其中包含自第一个5.0里程碑版本以来的所有更改,
在GitHub上 。 当心BREAKING更改。

感谢所有使生菜5成为可能的贡献者。 感谢任何反馈或在GitHub上提出问题 。

动态Redis命令API

Redis命令接口抽象为类型安全的Redis命令调用提供了一种动态方式。 它允许您使用命令方法声明接口,以显着减少调用Redis命令所需的样板代码。

Redis是一个数据存储,支持190多个已记录命令和450多个命令排列。 对于客户端开发人员和Redis用户而言,命令的增长和对即将发布的模块的跟踪是一项挑战,因为单个Redis客户端中的每个模块都没有完整的命令覆盖范围。

用Lettuce调用自定义命令需要几行代码来定义传递参数的命令结构并指定返回类型。

RedisCodec<String, String> codec = StringCodec.UTF8;
RedisCommands<String, String> commands = ...String response = redis.dispatch(CommandType.SET, new StatusOutput<>(codec),new CommandArgs<>(codec).addKey(key).addValue(value));

Lettuce Command Interface抽象中的中心接口是Commands

该界面主要用作标记界面,可帮助您发现扩展该界面的界面。 您可以声明自己的命令接口和参数序列,其中命令名称是从方法名称派生的,或由@Command提供。 引入新命令不需要您等待新的Lettuce版本,但是它们可以通过自己的声明来调用命令。
该接口还可以根据用例支持不同的键和值类型。

根据方法声明,命令是同步执行,异步执行还是使用反应执行模型执行。

public interface MyRedisCommands extends Commands {String get(String key); // Synchronous Execution of GET@Command("GET")byte[] getAsBytes(String key); // Synchronous Execution of GET returning data as byte array@Command("SET") // synchronous execution applying a TimeoutString setSync(String key, String value, Timeout timeout);Future<String> set(String key, String value); // asynchronous SET execution@Command("SET")Mono<String> setReactive(String key, String value); // reactive SET execution using SetArgs@CommandNaming(split = DOT) // support for Redis Module command notation -> NR.RUNdouble nrRun(String key, int... indexes);
}RedisCommandFactory factory = new RedisCommandFactory(connection);MyRedisCommands commands = factory.getCommands(MyRedisCommands.class);String value = commands.get("key");

Redis命令界面给您带来了很多新的可能性。 其中之一是透明的反应式采用。 Lettuce的反应式API基于Reactive Streams,但是通过命令接口,您可以声明RxJava 1或RxJava 2返回类型,Lettuce将为您处理采用。 RxJava 1用户的迁移路径允许使用本机类型而无需
进一步转换。

另请参阅: https : //lettuce.io/core/5.0.0.RELEASE/reference/#redis-command-interfaces

命令界面批处理

命令接口支持命令批处理,以在批处理队列中收集多个命令,并通过一次写入传输将批处理刷新。 命令批处理以延迟的方式执行命令。 这意味着在调用时没有可用的结果。 批处理只能用于没有返回值(void)的同步方法或返回RedisFuture的异步方法。

可以在两个级别上启用命令批处理:

  • 在类级别,通过使用@BatchSize注释命令界面。 所有方法都参与命令批处理。
  • 在方法级别,通过将CommandBatching添加到参数中。 方法有选择地参与命令批处理。
@BatchSize(50)
interface StringCommands extends Commands {void set(String key, String value);RedisFuture<String> get(String key);RedisFuture<String> get(String key, CommandBatching batching);
}StringCommands commands = …commands.set("key", "value"); // queued until 50 command invocations reached.// The 50th invocation flushes the queue.commands.get("key", CommandBatching.queue()); // invocation-level queueing control
commands.get("key", CommandBatching.flush()); // invocation-level queueing control,// flushes all queued commands

了解更多: https : //lettuce.io/core/5.0.0.RELEASE/reference/#command-interfaces.batch

迁移到反应流

Lettuce 4.0引入了基于RxJava 1和Observable的反应式API。 这是响应式Redis支持的开始。 生菜在各处都使用Observable ,因为其他反应式(如SingleCompletable )仍处于测试阶段或正在开发中。

从那时起,反应空间发生了很多变化。 RxJava 2是RxJava 1的后继产品,现已到期。 RxJava 2并不完全基于Java 6的响应流和基线,而其他合成库也可以从Java 8中受益。

这也意味着,没有null值,并且使用专用值类型来表示API上的值多重性( 0|10|1|N )。

在Lettuce 5.0中,反应式API使用Project Reactor及其MonoFlux类型。

生菜4

Observable<Long> del(K... keys);Observable<K> keys(K pattern);Observable<V> mget(K... keys);

生菜5

Mono<Long> del(K... keys);Flux<K> keys(K pattern);Flux<KeyValue<K, V>> mget(K... keys);

从RxJava 1切换到Project Reactor的使用需要切换库。 大多数运营商使用相似甚至相同的名称。 如果需要坚持使用RxJava 1,请使用rxjava-reactive-streams采用反应类型(RxJava 1 <-> Reactive Streams)。

迁移到反应流需要值包装以指示不存在值。 在命令可以返回null值的情况下,您会发现与以前的API和同步/异步API相比有所不同。 Lettuce 5.0附带了新的Value类型,这些类型是封装值(或不存在)的单子。

另请参阅: https : //lettuce.io/core/5.0.0.RELEASE/reference/#reactive-api

值,键值和其他值类型

反应式故事促进了不可变类型的实现,因此此发行版增强了现有的值类型并引入了新的类型以减少null使用并促进函数式编程。

值类型是基于ValueKeyValue / ScoredValue延伸从那里。 值是封装值或不存在的包装器类型。 Value可以通过不同的方式创建:

Value<String> value = Value.from(Optional.of("hello"));Value<String> value = Value.fromNullable(null);Value<String> value = Value.just("hello");KeyValue<Long, String> value = KeyValue.from(1L, Optional.of("hello"));KeyValue<String, String> value = KeyValue.just("key", "hello");

它转换为OptionalStream以与其他功能用途集成,并允许值映射。

Value.just("hello").stream().filter(…).count();KeyValue.just("hello").optional().isPresent();Value.from(Optional.of("hello")).map(s -> s + "-world").getValue();ScoredValue.just(42, "hello").mapScore(number -> number.doubleValue() * 3.14d).getScore();

您还将发现,所有值类型的公共字段都用getter封装,并且这些字段不再可访问。

退避/延迟策略

感谢@jongyeol

当运行具有大量使用Redis的服务的基于云的服务时,一旦分区结束,网络分区将严重影响Redis服务器的连接。 网络分区会同时影响所有断开连接的应用程序,并且所有节点或多或少会同时开始重新连接。

分区结束后,大多数应用程序将同时重新连接。 随着重新连接时间的随机化,抖动回退策略可以充分利用这种影响。

生菜具有各种退避实现:

  • 均等抖动
  • 全抖动
  • 与装饰相关的抖动

这些在ClientResources中配置:

DefaultClientResources.builder().reconnectDelay(Delay.decorrelatedJitter()).build();DefaultClientResources.builder().reconnectDelay(Delay.equalJitter()).build();

另请参阅: https : //www.awsarchitectureblog.com/2015/03/backoff.html和
https://lettuce.io/core/5.0.0.RELEASE/reference/#clientresources.advanced-settings

Z…RANGE命令的新API

排序集范围命令附带有关方法重载的简化API。 ZRANGEBYSCORE ,诸如ZRANGEBYSCOREZRANGEBYLEXZREMRANGEBYLEX等命令声明了接受RangeLimit对象而不是不断增长的参数列表的方法。 新的Range允许分数和值类型应用适当的二进制编码。

4.2及更早版本

commands.zcount(key, 1.0, 3.0)commands.zrangebyscore(key, "-inf", "+inf")commands.zrangebyscoreWithScores(key, "[1.0", "(4.0")commands.zrangebyscoreWithScores(key, "-inf", "+inf", 2, 2)

从5.0开始

commands.zcount(key, Range.create(1.0, 3.0));commands.zrangebyscore(key, Range.unbounded());commands.zrangebyscoreWithScores(key, Range.from(Boundary.including(1.0), Boundary.excluding(4.0));commands.zrangebyscoreWithScores(key, Range.unbounded(), Limit.create(2, 2));

再见了番石榴

Lettuce 5.0不再使用Google的Guava库。 Guava是Java 6兼容时代的好朋友, Future同步和回调很无聊。 随Java 8和CompletableFuture改变了。

HostAndPortLoadingCache等其他用途可以被内联或替换为Java 8的Collection框架。

删除不推荐使用的接口和方法

此发行版删除了不推荐使用的接口RedisConnectionRedisAsyncConnection及其分离的接口,而支持StatefulRedisConnectionRedisCommands

使用该API时,您会发现细微的差别。 事务命令和数据库选择不再通过Redis Cluster API可用,因为旧API是从独立API派生的。 RedisCommandsRedisAsyncCommands不再是Closeable 。 请使用commands.getStatefulConnection().close()关闭连接。 此更改消除了关闭命令界面和关闭连接的歧义。

连接池更换

花了相当长的时间,但4.3不赞成使用Lettuce的现有连接池支持。 特别是RedisClient.pool(…)RedisClient.asyncPool(…) 。 这些方法在Lettuce 5.0中已删除。

连接池的支持非常有限,并且将需要额外的重载,从而使API混乱以暴露所有支持的连接的池。 此版本带来了一个可定制且不会污染API的替代品。 ConnectionPoolSupport提供了一些方法来创建接受工厂方法和池配置的连接池。

返回的连接对象是在调用close()时将连接返回到其池的代理。 StatefulConnection实施Closeable允许使用try-with-resources。

GenericObjectPool<StatefulRedisConnection<String, String>> pool = ConnectionPoolSupport.createGenericObjectPool(() -> client.connect(), new GenericObjectPoolConfig());try(StatefulRedisConnection<String, String> connection = pool.borrowObject()) {// Work
}pool.close();

Redis集群拓扑刷新共识

群集拓扑刷新在某些情况下(动态拓扑源)可能导致孤立。 如果从群集中删除了群集节点,而生菜决定接受该已删除节点的拓扑视图,则可能会发生这种情况。 生菜卡在该节点上,无法使用剩余的群集。

此版本引入了PartitionsConsensus策略,以便在获取多个视图时确定最合适的拓扑视图。 可以通过重写RedisClusterClient.determinePartitions(Partitions, Map<RedisURI, Partitions>)定义策略。

生菜默认选择具有大多数先前已知群集节点的拓扑视图。 这有助于生菜坚持由最多节点组成的群集。

另请参阅: https : //github.com/lettuce-io/lettuce-core/issues/355

Redis集群中的异步连接

RedisClusterClient现在异步连接,而没有中间阻塞到集群节点。 连接进度在之间共享
多个线程首次请求群集节点连接。 以前,连接是顺序同步的。 每次连接尝试都会阻止其他线程的后续尝试。 如果群集节点连接超时,则线程将受到等待时间增加的惩罚。 如果说有10个线程等待连接,则最后一个线程必须等待多达10倍的连接超时。

异步连接一旦在内部使用Future即可启动连接,因此多个并发连接尝试会共享结果Future 。 错误现在可以更快地失败,并且群集节点的使用完全异步,无需同步,也没有陷入线程死锁的危险。

Redis Cluster Pub / Sub关于节点选择

RedisClusterClient.connectPubSub()现在返回一个StatefulRedisClusterPubSubConnection ,该StatefulRedisClusterPubSubConnection允许RedisClusterPubSubListener的注册以及在特定集群节点上的预订。

特定于群集节点的订阅允许使用键空间通知。 密钥空间通知不同于用户空间Pub / Sub,因为密钥空间通知不会广播到整个集群,而是仅在发生通知的节点上发布。 一个常见的用例是密钥在集群中过期。

StatefulRedisClusterPubSubConnection connection = client.connectPubSub();connection.addListener(…);connection.setNodeMessagePropagation(true);RedisClusterPubSubCommands<String, String> sync = connection.sync();
sync.slaves().commands().psubscribe("__key*__:expire");

本地运输

如果操作系统是合格的并且依赖项可用,则Lettuce现在默认情况下使用本机传输。 Lettuce从4.0版本开始支持epoll(在基于Linux的系统上),从此版本开始支持kqueue(基于BSD的系统,如macOS)。

可以通过设置io.lettuce.core.epoll=false来禁用Epoll的使用和系统属性。 以类似的方式,可以禁用kqueue
io.lettuce.core.kqueue=false

Epoll依赖性:

<dependency><groupId>io.netty</groupId><artifactId>netty-transport-native-epoll</artifactId><version>${netty-version}</version><classifier>linux-x86_64</classifier>
</dependency>

Kqueue依赖项:

<dependency><groupId>io.netty</groupId><artifactId>netty-transport-native-kqueue</artifactId><version>${netty-version}</version><classifier>osx-x86_64</classifier>
</dependency>

翻译自: https://www.javacodegeeks.com/2017/09/redis-client-lettuce-5-ga-released.html

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

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

相关文章

NOIP模拟测试14「旋转子段·走格子·柱状图」

旋转子段 连60分都没想&#xff0c;考试一直肝t3&#xff0c;t2&#xff0c;没想到t1最简单 我一直以为t1很难&#xff0c;看了题解发现也就那样 题解 性质1 一个包含a[i]旋转区间值域范围最多为min(a[i],i)----max(a[i],i) 感性理解 举个例子,例如3 7 1 4 5 6 2 这个子段包含a…

检测域名是否到期

如果你想做一个网站&#xff0c;首先需要购买一个域名&#xff0c;与其说是购买不如说是租用&#xff0c;因为你要想使用这个域名&#xff0c;每年都需要缴纳一笔费用。既然是租用&#xff0c;所以就有期限&#xff0c;在到期前没有续费&#xff0c;则该域名会被收回&#xff0…

jax-ws cxf_走向REST:在Spring和JAX-RS(Apache CXF)中嵌入Jetty

jax-ws cxf对于服务器核心Java开发人员来说&#xff0c;向世界“展示”的唯一方法是使用API​​。 今天的帖子都是关于JAX-RS的 &#xff1a;使用Java编写和公开RESTful服务。 但是&#xff0c;我们不会使用涉及应用程序服务器&#xff0c;WAR打包以及诸如此类的传统的重量级方…

问题 1046: [编程入门]自定义函数之数字后移

题目描述有n个整数&#xff0c;使前面各数顺序向后移m个位置&#xff0c;最后m个数变成前面m个数。写一函数&#xff1a;实现以上功能&#xff0c;在主函数中输入n个数和输出调整后的n个数。输入输入数据的个数n n个整数 移动的位置m输出移动后的n个数样例输入10 1 2 3 4 5 6 7…

Reliable Multicast Programming(PGM)协议

Reliable Multicast Programming (PGM)实际通用可靠多播协议&#xff0c;在某种程度上保证多播的可靠性。是IP上层协议&#xff0c;和TCP还有UDP同级&#xff0c;工作在传输层。 在组播传输视频项目中&#xff0c;发现在网络较差的时候&#xff0c;组播传输视频性能下降迅猛&am…

P1488 肥猫的游戏

P1488 肥猫的游戏https://www.luogu.org/problem/P1488 博弈论一个三角形&#xff0c;只有三种情况&#xff1a;1邻接&#xff0c;2邻接&#xff0c;3邻接主要是2邻接的情况比较麻烦边<0,n-1>需要特判一下 #include <iostream> #include <cstdio> #include &…

使用OAuth2令牌的安全REST服务

1.简介 在本教程中&#xff0c;我们将介绍如何将Spring Security与OAuth结合使用以保护REST服务。 在演示应用程序中&#xff0c;可以使用路径模式&#xff08; / api / ** &#xff09;访问服务器上受保护的REST资源&#xff0c;以便基于该路径的请求URL映射到不同的控制器方法…

java 内联调用深度_Java中内联虚拟方法调用的性能

java 内联调用深度总览 动态编译的好处之一是它能够支持在虚拟方法代码上的广泛方法内联。 内联代码可提高性能时&#xff0c;代码仍必须检查类型&#xff08;以防由于优化而更改了类型&#xff09;或在多个可能的实现之间进行选择。 这导致了问题。 通过接口调用的方法的多个…

组件切换方式(Vue.js)

这里&#xff0c;我用一个注册登录两组件的切换实例来演示&#xff1a; 切换方式一 <!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8" /><title>独秀不爱秀</title> </head><body><div …

在GWT中序列化/反序列化Json

JSON和GWT 最近&#xff0c; GWT用户小组中进行了有趣的讨论 &#xff0c;涉及在客户端对JSON进行序列化/反序列化的最佳实践。 这篇文章旨在突出其重点。 到目前为止&#xff0c;在GWT中有三种将对象转换为JSON并从客户端转换回JSON的方法&#xff1a; gwt-jackson框架&#…

NOIP模拟测试15「建造城市city(插板法)·轰炸·石头剪刀布」

建造城市 题解 先思考一个简单问题 10个$toot$ 放进5间房屋&#xff0c;每个房屋至少有1个$toot$&#xff0c;方案数 思考&#xff1a;插板法&#xff0c;$10$个$toot$有$9$个缝隙&#xff0c;$5$间房屋转化为$4$个挡板&#xff0c;放在toot缝隙之间得到$C_{9}^{4}$ 10个$toot$…

弹簧和线程:TaskExecutor

在Web应用程序中使用线程并不常见&#xff0c;尤其是当您必须开发长期运行的任务时。 考虑到spring&#xff0c;我们必须格外注意并使用它已经提供的工具&#xff0c;而不是生成我们自己的线程。 我们希望线程由spring管理&#xff0c;因此能够在不产生任何影响的情况下使用应…

数位dp从会打模板到不会打模板

打了几个数位$dp$&#xff0c;发现自己除了会打模板之外没有任何长进&#xff0c;遇到非模板题依然什么都不会 那么接下来这篇文章将介绍如何打模板&#xff08;滑稽&#xff09; 假设我们要处理$l----r$ 采用记忆化搜索的方式&#xff0c;枚举$<r$每一种情况&#xff0c;枚…

javafx简单吗_JavaFX即将推出您附近的Android或iOS设备吗?

javafx简单吗已经有大新闻最近在世界上的JavaFX的关于JavaFX的是许多更多的组件开源&#xff0c;开源的广告在2012 JavaOne大会 。 在2月的开放源代码更新中 &#xff0c; Richard Bair编写了一份JavaFX项目表&#xff0c;该表在撰写本文时&#xff08;2013年2月11日&#xff0…

【webrtc】webrtc的rtp重传代码分析

pgm不太能用&#xff0c;没有想象中的可靠&#xff0c;重传机制貌似仍然使用组播重传&#xff0c;丢包率80%的网络感觉没啥改进&#xff0c;如果有所好转延迟估计也是个不小的问题。 后听说rtp也有nack机制&#xff0c;webrtc基于rtp实现了重传在一定程度上保证可靠性。 在各路…

了解java.nio.file.Path – 1

介绍 Java的最后几个发行版本&#xff0c;即Java 7&#xff0c;Java 8和即将到来的Java 9&#xff0c;具有许多功能&#xff0c;这些功能使Java开发人员的生活更加轻松。 &#xff08;我知道Java 9会使它变得更困难&#xff0c;但是只有在您采用新的范例时才可以。之后&#xf…

socket-01

对于所有的Web应用&#xff0c;本质上其实就是一个socket服务端&#xff0c;用户的浏览器其实就是一个socket客户端 转载于:https://www.cnblogs.com/yanhuaqiang/p/11329925.html

ActionScript3学习笔记2-包

在 ActionScript 3.0 中&#xff0c;包是用命名空间实现的&#xff0c;但包和命名空间并不同义。在声明包时&#xff0c; 可以隐式创建一个特殊类型的命名空间并保证它在编译时是已知的。显式创建的命名空间在 编译时不必是已知的。 下面的示例使用 package 指令来创建一个包含…

grep v grep_使用grep4j轻松测试分布式组件上的SLA

grep v grep因此&#xff0c;您的分布式体系结构如下图所示&#xff0c;您刚刚从企业那里收到了一项要求&#xff0c;以确保生产者发送并随后传输到下游系统&#xff08;消费者&#xff09;的消息的SLA必须快且永远不会慢于此。 400毫秒。 要求说&#xff1a; 从生产者发送到…

得到指定进程所有窗口。显示 影藏 置顶。

这里使用一个外挂程序测试&#xff0c;因为外挂程序没有做功能限制的处理 只是做了 窗口影藏。 全局变量 HWND hwnd[100]{0};int number0;DWORD Tpid0; 局部变量 char username[1028]; 先找到进程ID 1 HWND SelectPor() 2 { 3 bool isYesfalse; 4 string porcessName&q…