java redis 命令_命令界面:使用Java中的动态API处理Redis

java redis 命令

Redis是一个数据存储,支持190多个文档化命令和450多个命令排列。 社区积极支持Redis开发; 每个主要的Redis版本都附带新命令。 今年,Redis向第三方供应商开放,以开发可扩展Redis功能的模块。 对于客户端开发人员和Redis用户而言,命令的增长以及对即将发布的模块的跟踪是一项挑战。

命令增长

对于客户端库,Redis中的命令增长是一项具有挑战性的业务。 多个客户端公开一个类型化的API,该API为每个Redis API调用声明一个方法(函数)签名。 静态声明对于使用很有帮助,但是大量的Redis命令使用大量方法签名来污染客户端。 某些命令可能以不同的方式执行,从而影响需要附加签名的响应类型( ZREVRANGEZREVRANGE … WITHSCORES )。 让我们仔细看看一些方法签名:

重新发行

# Get the values of all the given hash fields.
# 
# @example
#   redis.hmget("hash", "f1", "f2")def hmget(key, *fields, &blk)

杰迪斯

public List<String> hmget(final String key, final String... fields)

生菜

List<V>
public List<K> hmget(K key, K... fields)

声明的方法为开发人员提供类型安全和文档,但它们同时是静态的。 Redis引入新命令后,客户端供应商必须更改API,否则新命令将不可用。 大多数Redis客户端公开客户端调用API来执行自定义命令来解决此问题:

重新发行

client.call([:hmget, key] + fields)

杰迪斯

final byte[][] params = …;
jedis.sendCommand(HMGET, params);

生菜

lettuce.dispatch(CommandType.HMGET, new ValueListOutput<>(codec),
new CommandArgs<>(codec).addKey(key).addKey(field));

吉迪普斯

rce.accept(client -> client.sendCmd(Cmds.HMGET, "hash", "field1", "field2", …));

其他客户端(例如node_redis基于Redis命令创建函数原型。 这是对静态API的改进,因为它使API具有一定的灵活性。

构造Redis命令需要有关其请求和响应结构的知识。 这些知识被记录在调用代码内部的某个位置。 这很方便,因为您将其放在需要代码的地方,但是它也有一些缺点。 由于自定义命令是从方法内部运行的,因此自定义命令需要额外的精力才能重用。 不需要在许多客户端上找到的典型方法签名。 如果不遵循API组件方法,这种方法会使自省更具挑战性。 这是因为所有自定义命令使用不同的参数调用相同的方法。

具有固定参数列表的静态方法声明的性质仅限于仅接受提供的参数。 方法调用的上下文控件不能通过该方法应用。 例如,Lettuce提供了一个同步API,该API可以控制所有命令的命令超时,但不能控制命令调用级别。

让我们通过动态API处理Redis。

动态API

动态API是编程接口,因为它们遵循约定,因此具有一定的灵活性。 从Resteasy客户端代理或Spring Data的查询派生中可以知道动态API。 两者都是生活在用户区代码中的接口。 Resteasy / Spring Data检查接口并通过提供Java代理来实现这些接口。 这些接口(代理)上的方法调用将被拦截,检查并转换为相应的调用。 让我们看一下这对于Java和Redis如何工作:

一个简单的命令界面

public interface MyRedisCommands {List<String> hmget(String key, String... values);}

上面的接口声明了一个方法: List<String > hmget(String key, String... fields) 。 我们可以从该声明中得出某些信息:

  • 它应该同步执行-结果类型中没有声明异步或React性包装器
  • Redis命令方法返回一个String List -告诉我们有关命令结果的期望,因此我们期望使用Redis数组并将每个项目转换为字符串
  • 该方法名为hmget 。 因为这是唯一可用的详细信息,所以我们假设命令名为hmget
  • 定义了两个参数: String keyString... values 。 这告诉我们参数的顺序及其类型。 尽管Redis除了批量字符串外不接受任何其他参数类型,但我们仍然可以对参数进行转换-我们可以从声明的类型中推断出它们的序列化。

从上面调用的命令如下所示:

commands.hmget("key", "field1", "field2");

并转换为Redis命令:

HMGET key field1 field2

接口上的声明带有两个有趣的属性:

  1. 有一个方法签名。 尽管这是一个显而易见的事实,但它是一个常见的可执行文件。 它允许通过搜索此方法的引用来快速分析呼叫者。
  2. 在方法签名上方有一个空格,理想用于文档目的。

多种执行模型

public interface MyRedisCommands {List<String> hmget(Timeout timeout, String key, String... values);RedisFuture<List<String>> mget(String... keys);Flux<String> smembers(String key);}

动态API允许返回类型的差异。 让我们看看这如何影响我们可以从其返回类型派生的事物。

  • 您已经知道hmget以阻塞方式执行。 但是,等等,那Timeout参数是什么? 这是一个自己的参数类型,用于在调用级别上声明超时。 基础执行从参数应用超时,而不再是在连接级别设置的默认值。
  • mget声明一个RedisFuture返回类型,该返回类型包装StringListRedisFuture是用于异步执行的包装器类型,它返回一个句柄以在稍后阶段执行同步或方法链接。 该方法可以异步执行。
  • smembers使用String Flux 。 基于返回类型,我们可以期待两个属性: Flux是一个React式执行包装器,它将延迟执行直到订阅者订阅Flux为止。 List类型消失了,因为Flux可以发出0..N项目,因此我们可以决定进行流式响应执行。

命令结构

public interface MyRedisCommands {List<String> mget(String... keys);@Command("MGET")RedisFuture<List<String>> mgetAsync(String... keys);@CommandNaming(strategy = DOT)double nrRun(String key, int... indexes)@Command("NR.OBSERVE ?0 ?1 -> ?2 TRAIN")List<Integer> nrObserve(String key, int[] in, int... out)
}

Java要求方法的名称或参数类型有所不同。 字节码级别仅支持返回类型的差异,但在代码中编写方法时则不支持。 如果要声明一个同步执行的方法和一个采用相同参数异步执行的方法,该怎么办? 您需要指定其他名称。 但是,这是否与先前解释的名称派生冲突? 是的

  • 仔细看看mgetmgetAsync 。 两种方法均旨在同步和异步执行MGET命令。 mgetAsync带有@Command注释,该命令为命令提供命令名称,并覆盖该方法否则将命名为MGETASYNC的假设。
  • Redis对模块开放。 每个模块都可以通过提供新命令来扩展Redis,其中命令模式遵循<PREFIX>。<COMMAND>准则。 但是,Java方法名称中不允许使用点。 让我们使用@CommandNaming(strategy = DOT)将不同的命名策略应用于nrRun 。 骆驼驼峰(字母大小写的变化)通过在各个命令段之间放置一个点来表示,我们很NR.RUN从Neural Redis运行NR.RUN
  • 一些命令带有更复杂的语法,该语法不允许仅连接参数。 看一下NR.OBSERVE 。 它由三个静态部分组成,中间部分之间有参数。 该命令结构以类似命令的语言表示。 NR.OBSERVE ?0 ?1 -> ?2 TRAIN将命令描述为字符串,并为参数添加索引引用。 命令中的所有字符串部分都是常量,参数引用将替换为实际参数。

结论

将动态API应用于Redis可以将视图转移到新的视角。 它可以为用户提供简化的自定义命令方法,而不会牺牲可重用性。 方法声明的性质为调用者的文档记录和自省创造了条件。

动态API也对使用RESP的其他应用程序(例如Disque或Tile38)也有利 。

可从Sonatype的OSS Snapshot存储库https://oss.sonatype.org/content/repositories/snapshots/通过生菜获得实验性实现:

<dependency><groupId>biz.paluch.redis</groupId><artifactId>lettuce</artifactId><version>5.0.0-dynamic-api-SNAPSHOT</version>
</dependency>

使用RedisCommandFactory

RedisCommandFactory factory = new RedisCommandFactory(connection);TestInterface api = factory.getCommands(TestInterface.class);
String value = api.get("key");public interface TestInterface {String get(String key);@Command("GET")byte[] getAsBytes(String key);
}

参考

  • @Command :命令注释通过使用类似命令的语言来指定命令名称或整个命令结构。
  • @CommandNaming :用于指定命令命名策略的注释。
  • Timeout :包含超时的值对象。
  • RedisFuture :未来结果句柄。
  • Flux : React堆执行的Project Reactor发布者,发出0..N项目。

翻译自: https://www.javacodegeeks.com/2016/10/command-interfaces-approaching-redis-dynamic-apis-java.html

java redis 命令

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

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

相关文章

kettle 只有一个输入记录期待设置变量并且至少已经收到2个变量._OPNET学习笔记2...

双击主机网络打开对应的节点模型&#xff0c;从图中可以看到网络的分层&#xff1a;应用层&#xff0c;传输层&#xff0c;网络层&#xff0c;链路层&#xff1b;其中在传输层中我们用到的主要是UDP&#xff08;对实时性要求比较高&#xff09;&#xff0c;网络层又包括IP封装层…

oracle10g启动顺序,oracle 10g rac维护:开机 关机顺序,流程

维护oracle rac的时候&#xff0c;可能需要关闭数据库&#xff0c;甚至关闭服务器。具体的开机关机顺序如下&#xff1a;(oracle 用户下)1.关机顺序(1)关闭集群oememctl stop dbconsole -cluster(2)关闭数据库实例srvctl stop instance -d EDWPRD -i EDWPRD1srvctl stop instan…

python tkinter控件_Python3 tkinter基础 Label pack 设置控件在窗体中的位置

? python : 3.7.0 OS : Ubuntu 18.04.1 LTS IDE : PyCharm 2018.2.4 conda : 4.5.11 type setting : Markdown ? 普通布局 code """ Author : 行初心 Date : 18-10-1 Blog : www.cnblogs.com/xingchuxin GitHub : github.com/GratefulHeartCoder ""…

oracle的mins,分钟的英文缩写,10min还是10mins!

请问,分钟的英文缩写是min,小时的英文缩写是h,还是hr?秒的..._知乎[图文]时间分钟的英文缩写是什么minutes 10 minutes意思是十分钟的&#xff0c;比如说路程 10minutes就是十分钟 没有10minutes这种表达[图文]分钟 min【minute】 超过多少分钟就用介词past表示超过 还差几分钟…

lucene使用3.0.3_Jirasearch 2.0狗粮:使用Lucene查找我们的Jira问题

lucene使用3.0.3几年前&#xff0c;我首先构建并发布了Jirasearch &#xff0c;它是用于薄型包装Lucene服务器的有趣的狗粮测试用例&#xff0c;以针对我们的Jira问题公开强大的搜索UI。 这很好地展示了Lucene的许多重要功能&#xff1a; 使用块联接查询来建模父文档&#xf…

域名层级划分

文章目录教科书的定义域名结构示例教科书的定义 域名级数是指一个域名由多少级组成&#xff0c;域名的各个级别被 . 分开&#xff0c;最右边的那个词称为“顶级域名”。“顶级域名”又称之为“一级域名”&#xff0c;例如&#xff1a;.com、.org、.net、.cn 等。“二级域名”就…

java执行python脚本_使用Runtime.getRuntime().exec()在java中调用python脚本

举例有一个Python脚本叫test.py&#xff0c;现在想要在Java里调用这个脚本。假定这个test.py里面使用了拓展的包&#xff0c;使得pythoninterpreter之类内嵌的编译器无法使用&#xff0c;那么只能采用java调用控制台进程&#xff0c;即 Runtime.getRuntime().exec()&#xff0c…

linux 4.1.16 ftrace 进程调度,Linux内核进程调度overview(1)

一、概述决定何时、如何选择一个新进程运行的这组规则叫做&#xff1a;调度策略(scheduling policy)。Linux的调度是基于分时技术(time sharing)&#xff1a;多个进程以“时间多路复用”方式运行&#xff0c;因为CPU的时间呗分成“片”(slice)&#xff0c;给每个可运行进程分配…

postman测试工具,如何对参数使用md5加密

先创建环境变量password&#xff0c;并定义了变量值&#xff08;例如&#xff1a;123456&#xff09;访问登录接口通常是post提交登录用户名称和登录密码&#xff0c;且以json格式提交&#xff0c;所以在body-raw-json&#xff0c;填写json串如下图所示&#xff1a; 接着在pre-…

开源java性能分析工具_Java性能监控:您应该知道的5个开源工具

开源java性能分析工具鲜为人知但有用&#xff1a;开源应用程序性能监视的状态 对于任何应用程序来说&#xff0c;最重要的事情之一就是性能。 我们要确保用户获得他们能获得的最佳体验&#xff0c;并想知道我们的应用已启动并正在运行。 这就是为什么我们大多数人至少使用一种…

cmd编译可以通过执行没有结果_Go语言是如何完成编译的

Go语言是一门需要编译才能运行的编程语言&#xff0c;也就说代码在运行之前需要通过编译器生成二进制机器码&#xff0c;随后二进制文件才能在目标机器上运行&#xff0c;如果我们想要了解Go语言的实现原理&#xff0c;理解它的编译过程就是一个没有办法绕过的事情。预备知识想…

修改linux资源限制参数命令,linux passwd命令参数及用法详解--linux修改用户密码命令...

名称&#xff1a;passwd使用权限&#xff1a;所有使用者使用方式&#xff1a;passwd [-k] [-l] [-u [-f]] [-d] [-S] [username]说明&#xff1a;用来更改使用者的密码参数&#xff1a;-k keep non-expired authentication tokens-l 关闭账号密码。效果相当于rmod.html target…

如何通过postman测试需要登录授权的接口

思路 请求需要登录授权的接口&#xff0c;就意味着你要传token给接口&#xff0c;所以请求接口&#xff08;要测试的接口&#xff09;之前就要先获取token&#xff0c;因为登录成功后服务端才会返回token&#xff0c;而token又设置了时效&#xff0c;所以每次请求接口&#xf…

junit 静态方法_预期异常规则和模拟静态方法– JUnit

junit 静态方法今天&#xff0c;我被要求使用RESTful服务&#xff0c;所以我按照Robert Cecil Martin的TDD规则开始实施它&#xff0c;并遇到了一种测试预期异常以及错误消息的新方法&#xff08;对我来说至少是这样&#xff09;&#xff0c;因此考虑共享我的实现方法作为这篇文…

wordpress linux 目录,快速搭建WordPress(Linux)

作者&#xff1a;彭济环境要求一、配置LAMP(LinuxApacheMysqlPHP)1、安装apachesudo apt-get install apache2 //安装apache2apache2 -v //查看版本网页访问本机ip地址&#xff0c;查看是否安装成功2、安装phpsudo apt-get install php //安装phpphp -v //查看版本sudo apt-get…

postman测试工具中的js代码中的sendRequest()使用详解

发送get请求 const url http://115.28.108.130:5000/api/user/getToken/?appid136425; // 发送get请求 pm.sendRequest(url, function (err, res) {console.log(err ? err : res.text()); // 控制台打印请求文本 });发送表单格式post请求 //构造一个登录请求 const login…

atheros蓝牙设备驱动 小米_小米Air 13笔记本黑苹果WiFi蓝牙硬件改装方案二

该方案适合小米笔记本Air 13初代&#xff0c;适合小米笔记本PRO等型号&#xff0c;适合通用的预留有M.2 PCIE通道SSD卡槽的电脑。也是作者极力推荐的终极改造方案。总体方案: 使用笔记本主板上的M.2 nvme通道 SSD硬盘接口进行拓展。使用BCM943602CS专用的M.2[NGFF]转接卡进行改…

将经过身份验证的用户注入Spring MVC @Controllers

可以使用AuthenticationPrincipal批注和AuthenticationPrincipalArgumentResolver这是Spring MVS MethodArgumentResolver的实现&#xff09;将注入经过身份验证的用户注入Spring MVC处理程序方法。 默认情况下&#xff0c; AuthenticationPrincipalArgumentResolver已通过Web安…

Oracle数据库的命令工具sql*plus/sqlplus介绍

Oracle 的 sql*plus 是与 Oracle 数据库进行交互的客户端工具&#xff0c;借助 sql*plus 可以查看、修改数据库记录。在 sql*plus 中&#xff0c;可以运行sql*plus 命令与 SQL 语句。MySQL 中的 mysql、show、mysqldump 等命令就类似于 Oracle 的 sql*plus 客户端命令。 SQL 语…

python实现局域网攻击_通过python实现DNS欺骗

假设在一个的局域网内有两个人&#xff1a;Bob和Eve。Eve想让Bob访问他创建的恶意网页&#xff0c;这样她就可以通过隐藏性的下载给Bob的计算机上安装恶意软件&#xff0c;或者可能展示一个欺骗性的站点来试图窃取Bob的认证信息。&#xff08;图片来自以上提供的链接&#xff0…