管道与事务
了解如何使用 Redis 管道和事务
Redis 允许您将一系列命令一起批量发送到服务器。您可以使用两种类型的批量操作:
- 管道(Pipelines)通过在一次通信中将多个命令一起发送到服务器来避免网络和处理开销。然后服务器在一次通信中返回所有响应。有关更多信息,请参阅管道页面。
- 事务(Transactions)保证所有包含的命令都会完整执行,而不会被其他客户端的命令中断。有关更多信息,请参阅事务页面。
执行管道
hiredis
没有显式启动管道的命令,但如果您使用 redisAppendCommand()
函数发出命令,它会被添加到输出缓冲区中,而不会立即发送到服务器。
还有一个输入缓冲区用于接收命令的回复。如果您在输入缓冲区为空时调用 redisGetReply()
,它将首先发送输出缓冲区中排队的任何命令,然后等待回复到达输入缓冲区。之后它将只返回第一个回复。
如果您随后进行后续的 redisGetReply()
调用,它们会发现输入缓冲区不为空,并且仍然有先前命令排队的回复。在这种情况下,redisGetReply()
将仅从输入缓冲区中移除并返回回复,直到输入缓冲区再次为空。
下面的示例展示了如何同时使用 redisAppendCommand()
和 redisGetReply()
redisAppendCommand(c, "SET fruit:0 Apple");
redisAppendCommand(c, "SET fruit:1 Banana");
redisAppendCommand(c, "SET fruit:2 Cherry");
redisAppendCommand(c, "GET fruit:0");
redisAppendCommand(c, "GET fruit:1");
redisAppendCommand(c, "GET fruit:2");
redisReply *reply;
// Iterate once for each of the six commands in the
// pipeline.
for (int i = 0; i < 6; ++i) {
redisGetReply(c, (void**) &reply);
// If an error occurs, the context object will
// contain an error code and/or an error string.
if (reply->type == REDIS_REPLY_ERROR) {
printf("Error: %s", c->errstr);
} else {
printf("%s\n", reply->str);
}
freeReplyObject(reply);
}
// >>> OK
// >>> OK
// >>> OK
// >>> Apple
// >>> Banana
// >>> Cherry
redisAppendCommand()
的调用签名与 redisCommand()
相同,只是它不返回 redisReply
。还有一个 redisAppendCommandArgv()
函数,它类似于 redisCommandArgv()
(有关更多信息,请参阅发布命令)。
redisGetReply()
接收通常的上下文指针和一个指向 redisReply
指针的指针(您必须将其强制转换为 void**
)。redisGetReply()
返回后,回复指针将指向排队命令返回的 redisReply
对象(有关更多信息,请参阅处理命令回复)。
对添加到管道中的每个命令调用一次 redisGetReply()
。每次调用后都应检查错误,并在处理完每个回复对象后释放它,如上面的示例所示。
事务
hiredis
没有提供任何特殊的 API 来处理事务,但您可以使用 MULTI
、EXEC
和 WATCH
命令自行实现事务,就像您在 redis-cli
中使用它们一样。有关更多信息,请参阅事务。