dot 未来速度的变革即将在您所在的城市举行活动。

加入我们在 Redis 发布会

触发器和函数:将代码更靠近您的数据

开发人员可以使用 Redis 构建和维护实时应用程序。您可以创建自动执行数据更改时代码的 JavaScript 函数,这些函数直接在 Redis 数据库中执行,从而确保更低的延迟。

通常,应用程序处理业务逻辑操作,将代码发送到数据库执行。这是一个缓慢的过程,因为每次执行函数时,代码都会从客户端流到服务器。开发人员负责维护访问同一数据库的所有应用程序的代码一致性,无论代码是简单的请求还是复杂的数据操作,而且很多时候代码在应用程序之间重复。

遵循 Redis 宣言准则,我们反对复杂性,我们必须采取行动,找到解决这些挑战的解决方案。

四年前,我们推出了 RedisGears,这是我们平台中的第一个可编程性模型。开发人员在数据所在的平台中编写和执行脚本。但是,这些脚本是临时的,由每个客户端提供,这可能导致不一致。

沿着这个方向,在 Redis 7.0 中,我们引入了使用函数的脚本方法的初始实现。函数提高了可用性和持久性,因为它们是数据库的一部分,继承了数据复制和持久性的级别。

现在,我们很自豪地介绍可编程性的下一步。借助 Redis 7.2,我们引入了触发器和函数。这些功能增强了 Redis 的可编程性,扩展了服务器端功能,改进了函数在数据库中的执行方式和时间,并简化了直接在数据所在的平台中执行复杂业务逻辑的过程。

触发器和函数的基础知识

触发器和函数是通过 Redis Stack 提供的新一代可编程性。它允许开发人员在 Redis 数据库中直接对数据更改进行编程、存储和自动执行 JavaScript 代码。

此功能使开发人员能够定义事件(称为触发器)以在更靠近数据的位置执行函数。也就是说,开发人员定义响应数据库事件或命令执行的业务逻辑。这加快了代码和相关交互的速度,因为没有必要等待将代码从客户端带到数据库。

它还加快了对 Redis 中其他事件的响应时间,例如使用其他方法(例如 发布和订阅 (Pub/Sub) 事件)无法实时处理的键空间通知。

触发器和函数处理集群化数据库内的分布,在每个分片上安装库,并根据密钥所在的平台执行函数。

我们还推出了远程函数。远程函数允许您执行读取操作,这些操作可以访问任何分片中的数据,即使在集群化数据库中也是如此,因此您可以从每个函数访问所有数据。

它使用 JavaScript,这是最流行的编程语言

Redis 使用 Lua 进行脚本编写和函数编写。Lua 有很多好处,例如代码可重用性,但它不是专业开发人员常用的语言。根据2022 年 StackOverflow 开发人员调查,只有 3.2% 的开发人员在专业领域使用 Lua。

相比之下,三分之二的开发人员使用 JavaScript。使用知名语言降低了新 Redis 开发人员的采用门槛。这是一件不用学习的事情。

应用程序代码更易于支持和维护

触发器和函数的另一个好处是它降低了跨多个应用程序管理业务逻辑的复杂性。

当多个应用程序访问同一数据库时,开发人员必须协调应用程序如何以一致的方式处理数据。在每个应用程序中重复代码以验证数据、丰富搜索结果或在另一个应用程序进行更改时更新数据库是很常见的做法。

使用触发器和函数,不再需要在多个应用程序中重复代码。代码始终以相同的方式执行,按需或由数据库中的事件触发。

数据库事件实时处理

到目前为止,要在 Redis 中对数据库事件做出反应,开发人员需要依赖 Pub/Sub 机制。虽然 Pub/Sub 有很多优点,但它并不总是正确选择。特别是,Pub/Sub 不是实时的。客户端必须主动监听事件;如果客户端没有监听,事件就会丢失。

现在,开发人员可以注册键空间触发器,这些触发器根据密钥前缀和事件类型执行。可以在原子方式中执行触发器,以便在事件和业务逻辑之间不会处理其他 Redis 事件。

向我展示如何完成它

通过实际示例来理解事物总是更容易。在这里,我们介绍注册函数和触发器。当通过 TFCALL 命令调用函数时会执行该函数;触发器根据 Redis 中的事件执行。

序言定义了我们使用 js 引擎,库名称是 lib,并且所需的最小触发器和函数 API 版本是 1.0。

#!js name=lib api_version=1.0

接下来,我们创建一个返回 Redis 命令结果的函数。客户端允许在我们的函数中执行 Redis 命令。数据事件包含在运行函数时可以提供的键和参数。

function answer(client, data) {
	return client.call(“ping”);
}

Redis 全局变量允许您注册触发器和函数,并记录到日志文件。我们使用一个名称注册函数,在执行函数时使用该名称调用它。

redis.registerFunction(‘playPingPong’, answer);

完整的 JavaScript 文件如下所示。

#!js name=lib api_version=1.0

function answer(client, data) {
	return client.call(‘ping’);
}

redis.registerFunction(‘playPingPong’, answer);

将此文件保存为 lib.js

然后,我们使用 TFUNCTION LOAD 命令在触发器和函数中注册我们的函数。 TFUNCTION LOAD 命令还在集群化数据库中分发库。

> redis-cli  -x TFUNCTION LOAD < ./lib.js
OK

现在,我们可以使用 TFCALL 命令执行函数。该命令获取库名称和函数名称,用点号分隔。

>redis-cli TFCALL lib.playPingPong 0
“PONG”

通过这样做,您已成功在 Redis 数据库中创建、注册和触发函数。

我们可以使用键空间触发器扩展此示例。我们添加一个新的注册,该注册对以 '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);

使用带有 REPLACE 参数的 TFUNCTION LOAD 命令来更新现有的库。 TFUNCTION LOAD REPLACE 命令会立即更新使用 Redis 数据库的所有客户端,并开始使用新的业务逻辑。

>redis-cli -x TFUNCTION LOAD REPLACE . < ./lib.js
OK

要测试新的键空间触发器,请创建一个以 fellowship: 开头的密钥,并使用 RedisInsight 检查字段。键空间触发器与命令一起执行,因此在创建密钥时已添加last_updated字段。

Check the results in RedisInsight
在 RedisInsight 中检查结果

听起来很酷?自己试试吧

加入 Redis Stack 7.2 中的触发器和函数公共预览。通过在 Google Cloud/亚太地区 (东京) 或 AWS/亚太地区 (新加坡) 区域的 Redis Enterprise Cloud 中创建固定层数据库,或从我们的 下载中心 部署自管理实例,开始使用 Redis Stack 云。

触发器和函数的正式发布计划在 Redis 8 中进行。这将包括从预览用户那里收到的反馈,以及其他功能,例如定时触发器和更多调试选项。

欢迎在 Redis 邮件列表 上发表评论和反馈。