首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++ Redis mset 二進制數據封裝:三種方案深度對比

     編輯:關於C++

需求背景

使用 hiredis 客戶端批量寫入二進制鍵值對(mset)。標準 `redisCommand` 格式化字符串不支持二進制數據(遇 `\0` 截斷),需使用二進制安全接口 `redisCommandArgv`。

方案一:字符串拼接(僅適用文本)

void msetNotBinary(redisContext* c, const vector& keys, const vector& vals) {
    string cmd = "MSET";
    for (size_t i = 0; i < keys.size(); ++i)
        cmd += " " + keys[i] + " " + vals[i];
    void* r = redisCommand(c, cmd.c_str());
    // ... 錯誤處理
}

❌ 二進制數據會被截斷(如 `"AB\0DE"` 變為 `"AB"`)

方案二:手動構造 argv 數組

void mset1(redisContext* c, const vector& keys, const vector& vals) {
    int argc = keys.size() + vals.size() + 1;
    char** argv = new char*[argc];
    size_t* argvlen = new size_t[argc];
    
    int j = 0;
    argv[j] = new char[5]; memcpy(argv[j], "MSET", 4); argvlen[j] = 4; ++j;
    for (size_t i = 0; i < keys.size(); ++i) {
        argvlen[j] = keys[i].size();
        argv[j] = new char[argvlen[j]];
        memcpy(argv[j], keys[i].data(), keys[i].size()); ++j;
        argvlen[j] = vals[i].size();
        argv[j] = new char[argvlen[j]];
        memcpy(argv[j], vals[i].data(), vals[i].size()); ++j;
    }
    void* r = redisCommandArgv(c, argc, const_cast(argv), argvlen);
    // ... 釋放內存
}

✅ 二進制安全 ✅ 但手動內存管理繁瑣,`char**` 到 `const char**` 轉換需 `const_cast` 有風險

方案三:vector 封裝 argv(推薦)

void mset2(redisContext* c, const vector& keys, const vector& vals) {
    vector argv(keys.size() + vals.size() + 1);
    vector argvlen(keys.size() + vals.size() + 1);
    
    int j = 0;
    static const char* msetcmd = "MSET";
    argv[j] = msetcmd; argvlen[j] = 4; ++j;
    for (size_t i = 0; i < keys.size(); ++i) {
        argvlen[j] = keys[i].size();
        argv[j] = new char[argvlen[j]];
        memcpy(argv[j], keys[i].data(), keys[i].size()); ++j;
        argvlen[j] = vals[i].size();
        argv[j] = new char[argvlen[j]];
        memcpy(argv[j], vals[i].data(), vals[i].size()); ++j;
    }
    void* r = redisCommandArgv(c, argv.size(), &argv[0], &argvlen[0]);
    // ... 釋放 new 出的 char*
}

✅ 二進制安全 ✅ vector 自動管理指針數組生命周期 ✅ 代碼更清晰安全

驗證方法

# 非二進制安全:get D -> "AB"
# 二進制安全:  get D -> "AB\x00DE"

最佳實踐總結

  • 優先使用方案三:vector 封裝 + `redisCommandArgv`
  • 注意:`argv` 中的字符串內存需手動 `new`/`delete`,vector 只管理指針數組
  • 錯誤處理:檢查 `redisCommandArgv` 返回值,調用 `freeReplyObject`
  • 性能:批量 mset 遠優於多次 set,減少網絡往返

掌握 hiredis 二進制接口是構建高性能 Redis C++ 客戶端的關鍵技能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved