集群支持
触发器和函数的集群支持
注意:在 Redis 社区版集群上,在执行任何 Gears 函数之前,必须向所有分片发送 REDISGEARS_2.REFRESHCLUSTER
命令,以便它们了解集群拓扑。如果没有执行此步骤,每个分片将作为一个单独的 Redis 社区版实例运行。
触发器和函数支持在 Redis 集群上进行跨分片操作。这意味着可以调用一个将在另一个分片上执行的函数。我们将此类函数称为远程函数。
与本地函数一样,远程函数必须在库加载时使用 redis.registerClusterFunction
API 进行声明。以下示例声明了一个返回分片上键数量的远程函数
redis.registerClusterFunction("dbsize", async(async_client) => {
return client.block((async_client) => {
return client.call("dbsize").toString();
});
});
redis.registerClusterFunction
传递远程函数名称(稍后将用于调用远程函数)和远程函数代码。远程函数必须是一个协程(异步函数),它在后台远程分片上执行。有关异步函数的更多信息,请参考 同步和异步 页面。
我们有几种选项可以调用远程函数。这些选项通过传递给协程的异步客户端公开。
async_client.runOnShards
- 在所有分片(包括当前分片)上运行远程函数。返回一个 promise,一旦解析,将提供两个嵌套数组,第一个包含另一个数组,其中包含来自所有分片的结果,另一个包含错误数组([[res1, res2, ...],[err1, err2, ..]]
)。async_client.runOnKey
- 在负责给定键的分片上运行远程函数。返回一个 promise,一旦解析,将提供远程函数执行的结果,或在发生错误的情况下引发异常。
以下示例注册一个将返回集群上键总数的函数。该函数将使用上面定义的远程函数。
redis.registerAsyncFunction("my_dbsize", async(async_client) => {
let res = await async_client.runOnShards("dbsize");
let results = res[0];
let errors = res[1];
if (errors.length > 0) {
return errors;
}
let sum = BigInt(0);
results.forEach((element) => sum+=BigInt(element));
return sum;
});
首先,该函数在所有分片上执行一个远程函数,该函数返回每个分片上的键数量,然后该函数将所有结果相加并返回所有分片的键总数。
以下是完整示例
#!js name=lib api_version=1.0
redis.registerClusterFunction("dbsize", async(client) => {
return client.block((client) => {
return client.call("dbsize").toString();
});
});
redis.registerAsyncFunction("test", async(async_client) => {
let res = await async_client.runOnShards("dbsize");
let results = res[0];
let errors = res[1];
if (errors.length > 0) {
return errors;
}
let sum = BigInt(0);
results.forEach((element) => sum+=BigInt(element));
return sum;
});
参数和结果序列化
可以将参数传递给远程函数。参数将在 async_client
后传递给远程函数。以下示例展示了如何从集群中的任何分片获取键的值
#!js name=lib api_version=1.0
const remote_get = "remote_get";
redis.registerClusterFunction(remote_get, async(client, key) => {
let res = client.block((client) => {
return client.call("get", key);
});
return res;
});
redis.registerAsyncFunction("test", async (async_client) => {
return await async_client.runOnKey("x", remote_get, "x");
});
函数 test
将返回 x
的值,无论函数是在哪个分片上执行的。
远程函数参数和结果按以下方式序列化
- 如果参数类型为
ArrayBuffer
,则数据将按原样发送。 - 否则,RedisGears 将尝试使用
JSON.stringify
将给定参数(或返回值)序列化为 JSON。序列化失败将导致引发错误。
执行超时
远程函数将不允许无限运行,并将超时。超时时间段可以使用 remote-task-default-timeout 配置。当使用 async_client.runOnShards
API 时,超时将作为错误添加到错误数组中。当使用 async_client.runOnKey
时,超时将导致引发异常。
远程函数限制
列出的所有限制 协程 也适用于远程函数。远程函数还有一些额外的限制
- 远程函数只能执行读操作。尝试执行写操作将导致错误。
- 远程函数不能保证成功(例如,如果分片崩溃)。在这种情况下,将给出超时错误。