文章速览:
一般来说,应用程序处理业务的逻辑,是将执行代码发送到数据库。因此每次执行函数时,代码都会从客户端流入服务器,结果就是这个过程十分缓慢,甚至会出现代码在应用程序之间重复执行的情况。
而我们一向是反对复杂性的!
Redis Gears:四年前推出的RedisGears,是Redis平台内的第一个可编程模型,开发人员能在数据所在的地方编写并执行脚本。
Redis 7.0:Redis 7.0引入了带有函数的脚本方法,函数作为数据库的一部分,提高了可用性和持久性,继承了数据的复制和持久性级别。
Redis 7.2:Redis 7.2更进一步,引入了触发器和函数,以增强Redis的可编程性;扩展了服务器端功能;改进了数据库中执行功能的方式和时间;并促进了直接在数据所在的地方执行复杂的业务逻辑。
触发器和函数是通过Redis Stack提供的新一代可编程功能。它允许开发人员直接在Redis数据库中针对数据更改进行编程、存储和自动执行JavaScript代码。
1、开发人员可以定义事件(称为触发器)来执行更接近数据的函数。也就是说,开发人员定义响应数据库事件或命令而执行的业务逻辑。这加快了代码和相关交互的速度,因为无需等待即可将代码从客户端引入数据库。
2、加快对Redis中其他事件的反应时间,如键空间通知,这些通知无法通过发布和订阅(Pub/Sub)事件等其他方式实时处理。
3、远程功能:触发器和函数处理集群数据库内的分布,在每个分片上安装库并根据密钥所在的位置执行函数。远程函数允许执行读取操作,这些操作可以从任何槽访问数据,甚至在集群数据库中也是如此,因此可以从每个函数访问所有数据。
Redis使用Lua来编写脚本和函数。Lua有很多好处,例如代码可重用性,但它并不是专业开发人员常用的语言。根据2022 年StackOverflow开发者调查,只有 3.2% 的开发人员在专业领域使用 Lua。
因此,在Redis7.2中引入了JavaScript,这种更流行的语言的引入,可以降低新Redis开发人员的采用成本。
触发器和函数的另一个好处是它降低了跨多个应用程序管理业务逻辑的复杂性。
当多个应用程序访问同一数据库时,开发人员必须协调应用程序如何以一致的方式处理数据。在每个应用程序中复制代码以验证数据、丰富搜索结果,或在另一个应用程序进行更改时更新数据库也是很常见的。
有了触发器和函数,就不再需要在多个应用程序上重复代码。代码始终以相同的方式执行,按需执行或由数据库中的事件启动。
到目前为止,开发人员对Redis中的数据库事件做出反应需要依赖Pub/Sub机制。虽然 Pub/Sub有很多优点,但它并不总是正确的选择。特别是,Pub/Sub不是实时的。客户端必须主动监听事件;如果客户端没有监听,事件就会丢失。
在Redis7.2时代,开发人员可以注册基于键前缀和事件类型执行的键空间触发器。触发器可以以原子方式执行,因此在事件和业务逻辑之间不处理其他Redis事件。
这里,我们介绍如何注册一个函数和一个触发器。当通过TFCALL命令调用函数时,函数就会被执行;触发器根据Redis中的事件执行。
1.序言定义我们使用js引擎,库名称为lib,所需的触发器和函数API的最低版本为1.0。
#!js name=lib api_version=1.0
2.接下来,我们创建一个返回Redis命令结果的函数。客户端允许在我们的函数中执行Redis 命令。数据事件包含运行函数时可以提供的键和参数。
function answer(client, data) {
return client.call(“ping”);
}
3.Redis全局变量允许我们注册触发器和函数,并记录到日志文件中。我们为该函数注册一个名称,并在函数执行时调用它。
redis.registerFunction(‘playPingPong’, answer);
4.完整的JavaScript文件如下所示,将其另存为lib.js.
#!js name=lib api_version=1.0
function answer(client, data) {
return client.call(‘ping’);
}
redis.registerFunction(‘playPingPong’, answer);
5.然后我们使用命令在触发器和函数中注册我们的函数TFUNCTION LOAD。该TFUNCTION LOAD命令还可以在集群数据库中分发函数库。
> redis-cli -x TFUNCTION LOAD < ./lib.js
OK
6.现在我们可以使用TFCALL命令执行该函数。该命令获取以句点分隔的库名称和函数名称。
>redis-cli TFCALL lib.playPingPong 0
“PONG”
7.这样,就成功地在Redis数据库中创建、注册并触发了一个函数。
8.我们可以使用键空间触发器拓展这个示例。我们添加了一个新的注册,该注册对前缀为'fellowship:'的键做出反应。在lib.js文件末尾添加此代码。
function addLastUpdatedField(client, data) {
if(data.event == ‘hset’) {
var currentDateTime = Date.now();
client.call(‘hset’, data.key, ‘last_updated’, currentDateTime.toString());
}
}
redis.registerKeySpaceTrigger(‘addLastUpdated’, 'fellowship:', addLastUpdatedField);
9. 使用带有 REPLACE 参数的 TFUNCTION LOAD 命令来更新现有库。该TFUNCTION LOAD REPLACE命令立即更新所有使用 Redis 数据库的客户端,并且它们会开始使用新的业务逻辑。
>redis-cli -x TFUNCTION LOAD REPLACE . < ./lib.js
OK
10.要测试新的键空间触发器,请创建一个以Fellowship:开头的新键,并使用RedisInsight 检查字段。键空间触发器是通过命令执行的,因此在创建键时已经添加了last_updated字段。最后,我们可以在RedisInsight中查看结果。