二进制数据

处理二进制数据

默认情况下,触发器和函数会将所有数据解码为字符串,并在失败时引发错误。虽然这对大多数用户有用,但有时需要处理二进制数据。为了做到这一点,库开发人员必须考虑以下事项:

  1. 二元函数参数
  2. 二进制命令结果
  3. keyspace triggers上的二进制键名
  4. 二进制数据在stream triggers上触发

二元函数参数

可以指示触发器和函数不要将函数参数解码为JS Strings,使用redis.functionFlags.RAW_ARGUMENTS函数标志。在这种情况下,函数参数将作为JS ArrayBuffer提供。示例:

#!js api_version=1.0 name=lib
redis.registerFunction("my_set",
    (c, key, val) => {
        return c.call("set", key, val);
    },
    {
        flags: [redis.functionFlags.RAW_ARGUMENTS]
    }
);

上面的例子将允许我们设置keyval,即使它们是二进制数据。运行示例:

127.0.0.1:6379> TFCALL lib.my_set 1 "\xaa" "\xaa"
"OK"
127.0.0.1:6379> get "\xaa"
"\xaa"

请注意,call 函数也接受 JS ArrayBuffer 参数。

二进制命令结果

获取函数参数作为二进制数据是不够的。我们可能希望从Redis键中读取二进制数据。为了做到这一点,我们可以使用callRaw函数,它不会将结果解码为JS String,而是将结果作为JS ArrayBuffer返回。示例:

#!js api_version=1.0 name=lib
redis.registerFunction("my_get", 
    (c, key) => {
        return c.callRaw("get", key);
    },
    {
        flags: [redis.functionFalgs.RAW_ARGUMENTS]
    }
);

上述示例将能够获取二进制数据并将其返回给用户。例如:

27.0.0.1:6379> set "\xaa" "\xaa"
OK
127.0.0.1:6379> TFCALL lib.my_get 1 "\xaa"
"\xaa"

请注意,JS ArrayBuffer 可以通过函数返回,它将作为 bulk string 返回给客户端。

数据库触发器上的二进制键名称

keyspace触发器上,如果触发事件的键名是二进制的,data.key字段将为NULL。data.key_raw字段始终作为JS ArrayBuffer提供,并可以像以下示例中使用:

#!js api_version=1.0 name=lib
/* The following is just an example, in general it is discourage to use globals. */
var n_notifications = 0;
var last_key = null;
var last_key_raw = null;
redis.registerKeySpaceTrigger("consumer", "", function(client, data) {
    if (data.event == "set") {
        n_notifications += 1;
        last_data = data.key;
        last_key_raw = data.key_raw;
    }
});

redis.registerFunction("notifications_stats", async function(){
    return [
        n_notifications,
        last_key,
        last_key_raw
    ];
});

运行示例:

127.0.0.1:6379> set "\xaa" "\xaa"
OK
127.0.0.1:6379> TFCALL lib.notifications_stats 0
1) (integer) 1
2) (nil)
3) "\xaa"

更多信息请参见keyspace triggers

流消费者上的二进制数据

stream triggers上,如果键名是二进制的。data.stream_name字段将为NULL。data.stream_name_raw字段始终作为JS ArrayBuffer提供,并且在这种情况下可以使用。此外,如果流的内容是二进制的,它也会在data.record下显示为null。在这种情况下,可以使用data.record(它始终存在)并包含作为JS ArrayBuffer的数据。示例:

#!js api_version=1.0 name=lib
/* The following is just an example, in general it is discourage to use globals. */
var last_key = null;
var last_key_raw = null;
var last_data = null;
var last_data_raw = null;
redis.registerFunction("stats", function(){
    return [
        last_key,
        last_key_raw,
        last_data,
        last_data_raw
    ];
})
redis.registerStreamTrigger("consumer", new Uint8Array([255]).buffer, function(c, data){
    last_key = data.stream_name;
    last_key_raw = data.stream_name_raw;
    last_data = data.record;
    last_data_raw = data.record_raw;
})

运行示例:

127.0.0.1:6379> xadd "\xff\xff" * "\xaa" "\xaa"
"1659515146671-0"
127.0.0.1:6379> TFCALL foo.stats 0
1) (nil)
2) "\xff\xff"
3) 1) 1) (nil)
      2) (nil)
4) 1) 1) "\xaa"
      2) "\xaa"
RATE THIS PAGE
Back to top ↑