二进制数据

使用二进制数据

Redis 堆栈 Redis 社区版 Redis 企业软件 Redis 云 Redis 社区版 适用于 Kubernetes 的 Redis Enterprise 客户

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

  1. 二进制函数参数
  2. 二进制命令结果
  3. 键空间触发器上的二进制键名称
  4. 流触发器上的二进制数据

二进制函数参数

可以指示触发器和函数不要将函数参数解码为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]
    }
);

The above example will allow us to set key and val even if those are binary data. Run example:

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

Notice that the call function also accepts JS ArrayBuffer arguments.

Binary command results

Getting function arguments as binary data is not enough. We might want to read binary data from a Redis key. In order to do this we can use the callRaw function, which will not decode the result as a JS String and instead will return the result as a JS ArrayBuffer. Example:

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

The above example will be able to fetch binary data and return it to the user. For example:

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

Notice that a JS ArrayBuffer can be returned by a function, it will be returned to the client as bulk string.

Binary keys names on database triggers

On keyspace triggers, if the key name that triggered the event is binary, the data.key field will be NULL. The data.key_raw field is always provided as a JS ArrayBuffer and can be used as in the following example:

#!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
    ];
});

Run example:

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"

For more information see keyspace triggers.

Binary data on stream consumers

On stream triggers, if the key name is binary. The data.stream_name field will be NULL. The data.stream_name_raw field is always provided as a JS ArrayBuffer and can be used in this case. In addition, if the content of the steam is binary, it will also appear as null under data.record. In this case, it is possible to use data.record (which always exists) and contains the data as a JS ArrayBuffer. Example:

#!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;
})

Run Example:

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 ↑