Hiredis 构建 Redis 命令实战指南
一、同步命令构造
1.1 redisCommand(fmt, …)
最常用的同步接口即 redisCommand
,其原型如下:
void *redisCommand(redisContext *c, const char *format, ...);
-
参数
c
:已连接的redisContext*
format
:与printf
类似的格式字符串
// 基本用法:发送 SET foo bar
redisReply *reply = redisCommand(c, "SET foo bar");// 插值字符串:发送 SET key:1 Hello
char *myKeyNumber = "1", *myValue = "Hello";
redisReply *r2 = redisCommand(c, "SET key:%s %s", myKeyNumber, myValue);
支持二进制数据:%b
当需要存储或检索二进制数据(如向量嵌入)时,可使用 %b
,并在后面传入指针与长度:
char *entryNumber = "1";
char *embedding = "<binary data>";
size_t embLen = 13;
char *url = "https://redis.io/";redisReply *r3 = redisCommand(c,"HSET entry:%s embedding %b url %s",entryNumber,embedding, embLen,url
);
注意:除了
%%
外,不支持其它 printf 规格(例如%d
)。
1.2 redisCommandArgv(argv, argvlen)
当参数来自数组或包含多段二进制时,直接使用 redisCommandArgv
更安全:
void *redisCommandArgv(redisContext *c,int argc,const char **argv,const size_t *argvlen
);
- 示例:发送
SET greeting hello
const char *argv[] = {"SET", "greeting", "hello"};
const size_t argvlen[] = {3, 8, 5};
int argc = 3;redisReply *reply = redisCommandArgv(c, argc, argv, argvlen);
若传入 argvlen=NULL
,Hiredis 会调用 strlen()
,但遇二进制数据仍应显式提供长度数组。
二、异步命令构造
对于高并发场景,非阻塞地发送命令并处理回调极为关键。Hiredis 提供与同步接口对应的异步版本。
2.1 基础接口
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
);
-
参数
ac
:异步上下文redisAsyncContext*
fn
:可选的回调函数,命令执行完毕后触发privdata
:用户自定义数据,回调时原样传回format
/argv
:与同步接口一致
2.2 回调函数签名
void getCallback(redisAsyncContext *c, void *reply, void *privdata) {redisReply *r = reply;char *key = privdata;if (!r) {if (c->errstr) printf("errstr: %s\n", c->errstr);return;}printf("Key: %s, value: %s\n", key, r->str);// 使用完毕后优雅断开redisAsyncDisconnect(c);
}
2.3 示例:混合使用
// 1. 异步 SET,不关心结果
char *key = "testkey", *value = "testvalue";
redisAsyncCommand(ac, NULL, NULL, "SET %s %s", key, value);// 2. 异步 GET,需回调处理
redisAsyncCommand(ac, getCallback, key, "GET %s", key);
异步上下文在事件循环中调度,执行完所有回调后,可在回调内调用 redisAsyncDisconnect(ac)
进行优雅断开;若需立即释放,使用 redisAsyncFree(ac)
。
三、处理命令回复
所有命令回复均通过 redisReply
结构体返回,其 type
字段指示具体格式(字符串、整数、数组等),详见 Hiredis 文档的“Handle replies”章节。务必检查 reply->type
和 reply->str
/ reply->integer
等字段,以确保正确解析。
四、最佳实践与性能优化
- 二进制安全:凡涉及原始字节,统一使用带长度参数的
%b
或argvlen
,避免strlen()
截断。 - 复用 Context:长连接或连接池可显著减少频繁连接带来的开销。
- 批量命令:结合
MULTI
/EXEC
或 Lua 脚本,减少网络往返次数。 - 异步模式:高并发场景优先考虑异步接口,并合理使用回调释放资源。
- 错误处理:检查
c->err
、ac->errstr
及reply->type == REDIS_REPLY_ERROR
,以便日志告警和重试。
五、总结
Hiredis 虽然接口简洁,但通过 redisCommand
/redisCommandArgv
、redisAsyncCommand
/redisAsyncCommandArgv
,可完全满足同步与异步场景下对 Redis 的灵活访问需求。结合合适的错误检查、连接复用及批量操作设计,您的 C/C++ 应用即可实现高性能、低延迟的 Redis 通信能力。希望本文能帮助您快速上手 Hiredis,并在生产环境中游刃有余地构造各类 Redis 命令。