集群支持
触发器和函数的集群支持
注意:在 OSS 集群上,在执行任何齿轮函数之前,你必须向所有分片发送 REDISGEARS_2.REFRESHCLUSTER
命令,以便它们了解集群拓扑。如果没有此步骤,每个分片将充当一个单独的 OSS 实例。
触发器和函数支持对 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
时,超时会导致引发异常。
远程函数限制
在 协程 上列出的所有限制也适用于远程函数。远程函数还有一些额外的限制
- 远程函数只能执行读取操作。尝试执行写入操作会导致错误。
- 远程函数不能保证成功(例如,如果分片崩溃)。在这种情况下,将给出超时错误。