发出命令
构造命令并将它们发送到 Redis 服务器。
与其他客户端库不同,hiredis
没有提供用于构造各种 Redis 命令的广泛 API。但是,它确实提供了一个轻量级且灵活的 API,可以帮助您从自己的代码中构造命令并解析其回复。
以下部分详细描述了可用函数。
构造同步命令
使用 redisCommand()
函数向服务器发送命令
void *redisCommand(redisContext *c, const char *format, ...);
此函数接收一个 redisContext
指针和一个指向包含命令的字符串的指针(参阅 连接 了解如何获取上下文指针)。命令文本与等效的 redis-cli
命令相同。例如,要发出命令
SET foo bar
您将使用现有 redisContext* c
执行以下命令
redisReply *reply = redisCommand(c, "SET foo bar");
参阅 命令参考 以获取可与 hiredis
一起使用的 CLI 命令示例。文档其他部分的大多数代码示例也有一个 CLI 标签,显示与代码等效的命令序列。
命令字符串的解释方式类似于 printf()
的格式字符串,因此您可以使用 %s
格式说明符轻松地将代码中的字符串值插入到命令中
char *myKeyNumber = "1";
char *myValue = "Hello";
// This issues the command 'SET key:1 Hello'.
redisReply *reply = redisCommand(c, "SET key:%s %s", myKeyNumber, myValue);
您可能需要在命令中包含二进制数据(例如,将 向量嵌入 存储到 哈希 对象的字段中)。为此,请使用 %b
格式说明符并传递指向数据缓冲区的指针,后跟一个指示其长度(以字节为单位)的 size_t
值。如下面的示例所示,您可以在同一个格式字符串中自由混合使用 %s
和 %b
说明符。此外,您可以使用序列 %%
表示字面百分号,但不支持其他 printf()
说明符,例如 %d
。
char *entryNumber = "1";
char *embedding = "<binary data>";
char *url = "https://redis.ac.cn/";
size_t embLength = 13;
redisReply *reply = redisCommand(c,
"HSET entry:%s embedding %b url %s",
entryNumber,
embedding, embLength,
url
);
redisCommand()
函数有一个名为 redisCommandArgv()
的变体
void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);
这不接受格式字符串,而是从 argv
参数中传递的字符串数组构建命令。
使用 argc
值指定此数组的长度,并使用 argvlen
数组指定数组中每个字符串的长度。如果您为 argvlen
传递 NULL
,则该函数将尝试使用 strlen()
获取每个字符串的长度。但是,如果任何字符串包含二进制数据,则此方法无效,因此在这种情况下您应显式传递 argvlen
。下面的示例展示了如何使用 redisCommandArgv()
发送简单命令
const char *argv[3] = { "SET", "greeting", "hello"};
int argc = 3;
const size_t argvlen[] = {3, 8, 5};
redisReply *reply = redisCommandArgv(c, argc, argv, argvlen);
构造异步命令
使用 redisAsyncCommand()
和 redisAsyncCommandArgv()
函数异步向服务器发送命令
#include <hiredis/async.h>
.
.
.
int redisAsyncCommand(
redisAsyncContext *ac, redisCallbackFn *fn, void *privdata,
const char *format, ...);
int redisAsyncCommandArgv(
redisAsyncContext *ac, redisCallbackFn *fn, void *privdata,
int argc, const char **argv, const size_t *argvlen);
这些函数的工作方式与 redisCommand()
和 redisCommandArgv()
相同(参见上方的 构造同步命令),但它们有两个额外参数。第一个是指向可选回调函数的指针,第二个是指向您自定义数据的指针,执行时会将其传递给回调函数。如果您不需要使用它们,请为这两个指针传递 NULL
。
回调函数具有以下签名
void(redisAsyncContext *c, void *reply, void *privdata);
第一个参数是异步连接上下文,第二个是指向回复对象的指针。使用强制类型转换为 (redisReply *)
可以以通常的方式访问回复(参阅 处理命令回复 获取 redisReply
的完整描述)。最后一个参数是您在 redisAsyncCommand()
调用期间提供的自定义数据指针。它将不做任何修改地传递给您的函数。
以下示例展示了如何使用 redisAsyncCommand()
,无论是否带回复回调函数
// The callback expects the key for the data in the `privdata`
// custom data parameter.
void getCallback(redisAsyncContext *c, void *r, void *privdata) {
redisReply *reply = r;
char *key = privdata;
if (reply == NULL) {
if (c->errstr) {
printf("errstr: %s\n", c->errstr);
}
return;
}
printf("Key: %s, value: %s\n", key, reply->str);
/* Disconnect after receiving the reply to GET */
redisAsyncDisconnect(c);
}
.
.
.
// Key and string value to pass to `SET`.
char *key = "testkey";
char *value = "testvalue";
// We aren't interested in the simple status reply for
// `SET`, so use NULL for the callback and custom data
// pointers.
redisAsyncCommand(c, NULL, NULL, "SET %s %s", key, value);
// The reply from `GET` is essential, so set a callback
// to retrieve it. Also, pass the key to the callback
// as the custom data.
redisAsyncCommand(c, getCallback, key, "GET %s", key);
请注意,当您使用完连接后,通常应在回调函数中异步断开连接。使用 redisAsyncDisconnect()
优雅地断开连接,让待处理命令执行并激活其回调函数。使用 redisAsyncFree()
立即断开连接。如果这样做,则已执行命令的任何待处理回调函数将以 NULL
回复指针调用。
命令回复
redisReply
对象中的信息有几种格式,特定回复的格式取决于生成它的命令。参阅 处理回复 了解不同的回复格式以及如何使用它们。