一、同步命令構造
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 命令。