使用 hiredis 同步连接 Redis 需调用 redisConnectWithTimeout 设置超时(单位为 struct timeval),连接后必须检查 context->err;执行命令需按 redisReply->type 分支安全处理并调用 freeReplyObject 释放;二进制数据须用 redisCommandArgv;context 非线程安全且无自动重连,需手动管理连接与 reply 生命周期。

怎么用 hiredis 连 Redis 服务(同步模式)
hiredis 默认是同步阻塞的,连接失败或网络卡住会直接 hang 住线程。所以第一步必须设好超时,否则生产环境容易出问题。
-
redisConnect不支持超时,得用redisConnectWithTimeout - 超时单位是
struct timeval,不是毫秒——{1, 500000}表示 1.5 秒 - 连接后务必检查
context->err,不能只看指针是否为空(比如认证失败时指针非空但err非零)
struct timeval timeout = {1, 500000};
redisContext *c = redisConnectWithTimeout("127.0.0.1", 6379, timeout);
if (c == nullptr || c->err) {
if (c) {
fprintf(stderr, "Redis connection error: %s\n", c->errstr);
redisFree(c);
}
return -1;
}
怎么执行 SET/GET 命令并安全取返回值
hiredis 的 redisCommand 返回的是 redisReply*,但它的结构不是扁平的,类型判断和字段访问必须严格按 reply->type 分支处理,否则容易段错误或读错内存。
-
REDIS_REPLY_STRING才有str和len;REDIS_REPLY_INTEGER要用integer字段 -
REDIS_REPLY_NIL表示 key 不存在,此时str == nullptr,不能直接strlen - 所有
redisReply*必须用freeReplyObject释放,不释放会内存泄漏
redisReply *reply = (redisReply*)redisCommand(c, "SET mykey 'hello'");
if (reply && reply->type == REDIS_REPLY_STATUS && strcmp(reply->str, "OK") == 0) {
printf("SET success\n");
}
freeReplyObject(reply);
reply = (redisReply*)redisCommand(c, "GET mykey");
if (reply) {
if (reply->type == REDIS_REPLY_STRING) {
printf("GET result: %.*s\n", (int)reply->len, reply->str);
} else if (reply->type == REDIS_REPLY_NIL) {
printf("key not exists\n");
}
}
freeReplyObject(reply);
怎么处理批量命令和二进制安全数据
Redis 原生支持二进制 key/value,但 C 字符串习惯用 \0 截断,直接传 char* 会丢数据。hiredis 提供了带长度参数的接口,必须用它们。
- 避免用
redisCommand(c, "SET %b %b", key, key_len, val, val_len)这种格式化方式——它内部仍走 sprintf,对二进制不安全 - 改用
redisCommandArgv,手动构造redisArgv数组,每个元素带len - 批量操作别硬写多个
redisCommand,用 pipeline(即连续发命令+一次收回复)提升吞吐
const char *argv[4]; size_t argvlen[4]; argv[0] = "MSET"; argvlen[0] = 4; argv[1] = "key1"; argvlen[1] = 4; argv[2] = "val1"; argvlen[2] = 4; argv[3] = "key2"; argvlen[3] = 4; // 注意:MSET 后面要成对出现,这里只是示意结构 redisReply *r = (redisReply*)redisCommandArgv(c, 4, argv, argvlen);
为什么程序跑一会儿就卡死或崩溃
最常见的三个原因:连接未重连、reply 未释放、多线程共用 context。hiredis 的 redisContext 不是线程安全的,且没有自动重连机制。
立即学习“C++免费学习笔记(深入)”;
- 每次发命令前,检查
c->fd != -1和c->err == 0,任一不成立就得redisFree+ 重连 - 所有
redisCommand调用后,无论成功失败,都必须freeReplyObject(包括返回nullptr的情况) - 多线程场景下,每个线程必须有自己的
redisContext,或者用连接池管理(不能简单全局单例)
连接断开后 redisCommand 可能返回 nullptr,但 context 还活着,继续用会导致未定义行为——这个点最容易被忽略。











