C++ 中解锁 Redis

一、核心前提:选择 Redis C++ 客户端库

C++ 本身没有内置 Redis 客户端,主流选择是hiredis(官方推荐的 C 语言客户端,轻量、稳定,C++ 可直接调用),也是最基础、最常用的库。

1. 环境安装(以 Linux 为例)

bash

运行

复制代码
# 1. 安装hiredis库
sudo apt update
sudo apt install libhiredis-dev

# 2. 验证安装(查看库文件)
ls /usr/lib/x86_64-linux-gnu/libhiredis*

注:Windows 环境可下载 hiredis 源码编译,或使用 vcpkg 安装:vcpkg install hiredis

2. 编译指令

编写 C++ 代码后,编译时需链接 hiredis 库:

bash

运行

复制代码
g++ your_code.cpp -o redis_demo -lhiredis

二、C++ 操作 Redis 核心实战代码

以下是完整的 C++ 操作 Redis 示例,包含连接、字符串操作、哈希操作、列表操作、断开连接等核心场景:

cpp

运行

复制代码
#include <iostream>
#include <string>
#include <hiredis/hiredis.h>

using namespace std;

// 封装Redis连接函数
redisContext* connectRedis(const string& ip, int port, const string& password = "") {
    // 1. 建立连接(超时时间10秒)
    struct timeval timeout = {10, 0};
    redisContext* ctx = redisConnectWithTimeout(ip.c_str(), port, timeout);
    
    // 2. 检查连接错误
    if (ctx == nullptr || ctx->err) {
        if (ctx) {
            cerr << "连接Redis失败:" << ctx->errstr << endl;
            redisFree(ctx);
        } else {
            cerr << "Redis连接对象创建失败!" << endl;
        }
        return nullptr;
    }
    cout << "Redis连接成功!" << endl;

    // 3. 有密码则认证
    if (!password.empty()) {
        redisReply* reply = (redisReply*)redisCommand(ctx, "AUTH %s", password.c_str());
        if (reply == nullptr || reply->type == REDIS_REPLY_ERROR) {
            cerr << "Redis认证失败:" << (reply ? reply->str : "无返回") << endl;
            freeReplyObject(reply);
            redisFree(ctx);
            return nullptr;
        }
        freeReplyObject(reply);
        cout << "Redis认证成功!" << endl;
    }

    return ctx;
}

// 封装Redis命令执行函数
redisReply* executeRedisCommand(redisContext* ctx, const char* format, ...) {
    if (ctx == nullptr) {
        cerr << "Redis连接为空,无法执行命令!" << endl;
        return nullptr;
    }

    va_list args;
    va_start(args, format);
    redisReply* reply = (redisReply*)redisvCommand(ctx, format, args);
    va_end(args);

    // 检查命令执行错误
    if (reply == nullptr) {
        cerr << "命令执行失败:连接已断开" << endl;
        return nullptr;
    }
    if (reply->type == REDIS_REPLY_ERROR) {
        cerr << "Redis命令错误:" << reply->str << endl;
    }

    return reply;
}

int main() {
    // 1. 连接Redis(替换为你的Redis地址、端口、密码)
    string redis_ip = "127.0.0.1";
    int redis_port = 6379;
    string redis_pwd = ""; // 无密码则留空
    redisContext* ctx = connectRedis(redis_ip, redis_port, redis_pwd);
    if (ctx == nullptr) {
        return -1;
    }

    // 2. 核心操作1:字符串(String)- SET/GET
    cout << "\n===== 字符串操作 =====" << endl;
    redisReply* reply = executeRedisCommand(ctx, "SET user:name Tom");
    if (reply && reply->type == REDIS_REPLY_STATUS && strcmp(reply->str, "OK") == 0) {
        cout << "SET成功" << endl;
    }
    freeReplyObject(reply);

    reply = executeRedisCommand(ctx, "GET user:name");
    if (reply && reply->type == REDIS_REPLY_STRING) {
        cout << "GET user:name = " << reply->str << endl;
    }
    freeReplyObject(reply);

    // 3. 核心操作2:哈希(Hash)- HSET/HGETALL
    cout << "\n===== 哈希操作 =====" << endl;
    reply = executeRedisCommand(ctx, "HSET user:1 name Jerry age 20 gender male");
    if (reply && reply->type == REDIS_REPLY_INTEGER) {
        cout << "HSET成功,新增字段数:" << reply->integer << endl;
    }
    freeReplyObject(reply);

    reply = executeRedisCommand(ctx, "HGETALL user:1");
    if (reply && reply->type == REDIS_REPLY_ARRAY) {
        cout << "HGETALL user:1 = ";
        for (size_t i = 0; i < reply->elements; i += 2) {
            cout << reply->element[i]->str << ":" << reply->element[i+1]->str << " ";
        }
        cout << endl;
    }
    freeReplyObject(reply);

    // 4. 核心操作3:列表(List)- LPUSH/LRANGE
    cout << "\n===== 列表操作 =====" << endl;
    reply = executeRedisCommand(ctx, "LPUSH fruits apple banana orange");
    if (reply && reply->type == REDIS_REPLY_INTEGER) {
        cout << "LPUSH成功,列表长度:" << reply->integer << endl;
    }
    freeReplyObject(reply);

    reply = executeRedisCommand(ctx, "LRANGE fruits 0 -1");
    if (reply && reply->type == REDIS_REPLY_ARRAY) {
        cout << "LRANGE fruits = ";
        for (size_t i = 0; i < reply->elements; i++) {
            cout << reply->element[i]->str << " ";
        }
        cout << endl;
    }
    freeReplyObject(reply);

    // 5. 断开连接
    redisFree(ctx);
    cout << "\nRedis连接已断开" << endl;

    return 0;
}

三、核心代码解释

  1. 连接 Redis
    • redisConnectWithTimeout:带超时的连接函数,避免无限等待;
    • AUTH命令:Redis 有密码时必须执行认证,否则后续命令会报错。
  2. 命令执行
    • redisCommand/redisvCommand:执行 Redis 命令,支持格式化参数(类似printf);
    • redisReply:存储命令返回结果,需通过type判断返回类型(字符串、数组、整数、状态等)。
  3. 资源释放
    • freeReplyObject:必须释放每个redisReply,避免内存泄漏;
    • redisFree:断开连接时释放上下文对象。

四、常见问题与注意事项

  1. 返回值类型对应

    Redis 命令返回类型 redisReply->type 示例
    成功状态(OK) REDIS_REPLY_STATUS SET、DEL 命令
    字符串 / 数字 REDIS_REPLY_STRING GET、HGET 命令
    整数 REDIS_REPLY_INTEGER LPUSH、LLEN 命令
    数组 REDIS_REPLY_ARRAY HGETALL、LRANGE 命令
    错误 REDIS_REPLY_ERROR 语法错误、认证失败
  2. 异常处理

    • 连接断开后,redisContext->err会被置位,需重新连接;
    • 生产环境建议封装重连逻辑,避免单次连接失败导致程序退出。
  3. 进阶选择:若嫌 hiredis(C 风格)不够 "C++ 化",可选择封装后的 C++ 库:

    • redis-plus-plus:基于 hiredis 的现代 C++ 封装,支持 RAII、异步操作;
    • cpp_redis:轻量级异步 Redis 客户端,支持发布订阅、集群。

总结

  1. C++ 操作 Redis 的核心是使用hiredis 库 ,编译时需链接-lhiredis
  2. 核心流程:建立连接 → 执行命令(处理返回值) → 释放资源 → 断开连接;
  3. 需重点关注redisReply的类型判断和资源释放,避免内存泄漏和逻辑错误。
相关推荐
我是小鳄鱼1 小时前
Day 3: Bash 工具-- 30天复刻了一个 Claude Code
开发语言·bash
小小仙。1 小时前
IT自学第十八天
java·开发语言·算法
王老师青少年编程1 小时前
2025年3月GESP真题及题解(C++七级): 等价消除
c++·编程·题解·真题·gesp·七级·等价消除
Yupureki2 小时前
《算法竞赛从入门到国奖》算法基础:入门篇-贪心算法(上)
c语言·数据结构·c++·算法·贪心算法·visual studio
散峰而望2 小时前
【算法竞赛】队列和 queue
开发语言·数据结构·c++·算法·链表·github·线性回归
扶苏-su2 小时前
Java--打印流
java·开发语言
幽络源小助理2 小时前
SpringBoot+Vue旅游推荐系统源码 | 幽络源
java·开发语言·spring boot
忧郁的Mr.Li2 小时前
Redis的过期删除策略和内存淘汰策略
数据库·redis·缓存
烧饼Fighting2 小时前
统信UOS操作系统离线安装ffmpeg
开发语言·javascript·ffmpeg