C++Redis开发(Ubuntu 22.04)

一、引子:语言到底是怎么"连上" Redis 的

1.1 从 HTTP 博客得到的启发:协议先行

在 HTTP 那篇博客里我们分析过应用层协议,也自己实现了 Web 开发。当时得出的结论是:想要建立连接,最重要的是先把协议设计好。

所谓协议,就是通信双方事先约定好每一个字段的具体含义 ,并且实现对应的序列化(发送端编码)和反序列化(接收端解码)。只要双方遵守同一份协议,任何语言、任何库都能互相通信------这就是 Redis 能被 C++/Java/Python 等几十种语言连接的根本原因。

1.2 客户端库的本质三要素

一个 Redis 客户端库,本质上只做三件事:

要素 作用 对应产物
网络连接 建立 TCP 连接、发送/接收字节流 socket 层
协议编码 把命令序列化成 RESP 字节流 序列化
协议解码 把服务器返回的字节流解析成结构 反序列化

Redis 定义了协议,各语言社区基于协议实现了各自的客户端库。MySQL 同理(MySQL 协议 + Connector/C++ 等)。


二、RESP 协议详解

2.1 传输层协议

  • Redis 官方实现中,RESP 协议承载在 TCP (默认 6379 端口)或 Unix Domain Socket 上;
  • 官方不支持 UDP 传输;
  • 原因:数据库场景要求数据精确、不丢失、有序到达,TCP 的可靠字节流正好满足;UDP 不保证可靠性和顺序,只适合音视频、游戏帧这类"丢了就丢了"的场景。

2.2 RESP 的五种基本数据类型

RESP(REdis Serialization Protocol)是 Redis 自己设计的文本协议,一共 5 种类型:

类型 首字节 示例 含义
简单字符串 + +OK\r\n 状态回复
错误 - -ERR unknown command\r\n 错误信息
整数 : :1000\r\n 整数回复(如 INCR)
批量字符串 $ $6\r\nfoobar\r\n 二进制安全的字符串,$ 后是字节数
数组 * *2\r\n... 多条消息的集合

2.3 一个命令的完整序列化实例

客户端发送 SET name zhangsan,实际在 TCP 上传输的字节流是:

复制代码
*3\r\n$3\r\nSET\r\n$4\r\nname\r\n$8\r\nzhangsan\r\n

逐段拆解:

片段 含义
*3 数组,共 3 个元素(命令名 + 两个参数)
$3\r\nSET 批量字符串,长度 3,内容是 SET
$4\r\nname 批量字符串,长度 4,内容是 name
$8\r\nzhangsan 批量字符串,长度 8,内容是 zhangsan

服务器返回 OK 时,回复就是 +OK\r\n。这就是序列化和反序列化的全部秘密------看到这里你应该明白,自己动手写一个迷你客户端是完全可行的。


三、C++ 客户端选型:hiredis 与 redis-plus-plus

3.1 hiredis:Redis 官方 C 客户端

  • 由 Redis 官方组织维护(redis/hiredis);
  • 提供同步 API (redisConnect + redisCommand + redisReply)和异步 API (redisAsyncContext + 事件循环);
  • 是很多其他语言客户端的底层基石。

3.2 redis-plus-plus:基于 hiredis 的 C++ 封装

  • 作者 sewenew,仓库 https://github.com/sewenew/redis-plus-plus;
  • 底层依赖 hiredis ,但面向 C++ 重新设计了接口:Redis、RedisCluster、RedisSentinel、连接池、管道、事务、发布订阅等;
  • 符合现代 C++ 习惯(RAII、异常、可选值),这就是我们选它的原因。

3.3 选型对比

维度 hiredis redis-plus-plus
语言 C C++
维护方 Redis 官方 社区(sewenew)
接口风格 C 函数 + 手动管理内存 类封装 + RAII
连接池/集群 需自己写 内置
我们的选择 作为底层依赖 ✅ 主用

四、库的获取与安装

4.1 安装 hiredis:apt 一行搞定(从镜像源下载)

复制代码
sudo apt install libhiredis-dev

libhiredis-dev 是开发包,同时包含头文件 (/usr/include/hiredis/hiredis.h)和库文件 (/usr/lib/x86_64-linux-gnu/libhiredis.a 与 .so)。

4.2 拉取并编译 redis-plus-plus:

复制代码
git clone ​https://github.com/sewenew/redis-plus-plus​
cd redis-plus-plus

sudo apt install cmake      # 安装 cmake 工具
mkdir build && cd build     # build 目录:隔离生成文件,防止污染源码目录(不只是"好看")
cmake ..                    # ⚠️ 由 CMakeLists.txt 生成 Makefile(关键步骤)
make                        # 编译,产出静态库 libredis++.a
sudo make install           # 安装到 /usr/local 下

说明 :CMakeLists.txt 是构建脚本,cmake .. 负责把它翻译成 Makefile(也可以生成 Ninja 等),之后 make 编译是将对应.o文件包装成动静态库(这里只有静态库)、make install 把产物拷贝到系统路径。多数主流开源库都是这条流程。

4.3 apt 安装 vs 源码编译的区别

维度 apt 安装 git 源码编译
头文件位置 /usr/include 等默认路径 手动 make install 到 /usr/local/include
库文件位置 /usr/lib/x86_64-linux-gnu/ /usr/local/lib/
编译时 不需要手动写路径 头文件/库路径一般也要靠默认目录或手动指定
灵活性 只能用仓库里的版本 可自定义编译选项(如 C++ 标准)

apt 安装是优选,git 安装之后 make 要消耗时间

4.4 验证安装产物位置

复制代码
# 头文件(编译期需要,供 #include 使用)
find /usr -name "redis++.h"
# → /usr/local/include/sw/redis++/redis++.h
# 所以代码里写: #include <sw/redis++/redis++.h>

# 库文件(链接期需要)
find /usr -name "libredis++*"
# → /usr/local/lib/libredis++.a

为什么在/usr路径下find?因为大部分都是默认安装到这里的

五、编译与链接细节

5.1 静态库链接

redis-plus-plus 默认构建的是静态库。

5.2 三种正确的链接写法

⚠️ -l 选项后面只能跟库名 (去掉 lib 前缀和 .a/.so 后缀),不能跟完整路径。

写法一:直接给完整路径(把 .a 文件当普通输入文件)

复制代码
g++ -std=c++17 main.cpp /usr/local/lib/libredis++.a \
    /usr/lib/x86_64-linux-gnu/libhiredis.a -lpthread -o app

写法二:-L 指定搜索目录 + -l 指定库名(推荐,最常用)

复制代码
g++ -std=c++17 main.cpp -L/usr/local/lib -lredis++ \
    -L/usr/lib/x86_64-linux-gnu -lhiredis -lpthread -o app

写法三:默认路径直接用 -l (apt 装好的 hiredis 已在默认路径,-L 可省)

复制代码
g++ -std=c++17 main.cpp -lredis++ -lhiredis -lpthread -o app

要点 :-lredis++ 实际会被解析成"去 -L 目录里找 libredis++.a(或 .so)"

5.4 链接顺序与常见坑

  1. 顺序 :静态库之间有依赖时,被依赖的放后面 ------libredis++.a 依赖 hiredis,所以 -lredis++ 必须写在 -lhiredis 前面;
  2. C++ 标准 :redis-plus-plus 用到了较新的 C++ 特性,编译时加 -std=c++17(至少 -std=c++11);
  3. hiredis 找不到 :如果 hiredis 不是 apt 装的(自己编译的),cmake 阶段用 -DHIREDIS_ROOT=路径 指定;
  4. pthread :新版本 glibc 已把 pthread 并入 libc,但显式 -lpthread 兼容性最好,加上无妨。

六、如何登录GitHub及后续源码查询

6.1 访问GitHub

  1. magic (违法),不宣传,不支持
  2. 使用加速器,我们这里使用stream的加速器,watt toolkit (免费),对GitHub加速之后就可以使用通过代理服务器的方式进行访问

6.2 后续学习

关于 redis 的各种数据结构具体的 API 使用及细节,可以参考我的源码,里面注释自认为还是比较详细的 bksczm/redis_test: Repository for Redis testing exercises

感谢支持

相关推荐
zhangjw341 小时前
1-6 PostgreSQL 特色类型实战:数组、JSON & JSONB、枚举、范围类型
数据库·postgresql
杨云龙UP1 小时前
Oracle 同义词(SYNONYM)详解及 Toad for Oracle SQL 智能补全配置实战
运维·数据库·sql·oracle·同义词·toad·toad for oracle
goehou1 小时前
缓存该删还是该改,LLM 服务里的双写问题
redis·缓存·llm·一致性·系统设计
余槐i1 小时前
Spring Boot 3.2 偶发500无日志:线程池复用导致请求上下文丢失
spring boot·redis·后端·mysql·性能优化
倔强的石头_1 小时前
MongoDB迁移的新选项:在金仓KES上,用SQL管理文档数据
数据库
loulanyue_1 小时前
AI Agent记忆从不是向量库:Oracle拆解读写分离与记忆晋升门,终结无脑存聊天的伪智能——读Wojtek Pluta演讲
数据库·人工智能·oracle
曼岛_2 小时前
[图解密码学]第5章 对称加密基础
java·数据库·密码学
Decay__2 小时前
17_MySQL 监控体系构建 —— mysqld_exporter + Prometheus + Grafana 全栈实战
运维·数据库·sql·mysql·架构
ss2732 小时前
不用向量库,我用 MySQL 跑通了蔬菜 RAG--基于 RuoYi-AI 的蔬菜种植知识库 + 智能咨询系统,普通开发机就能跑
数据库·人工智能·智慧农业·ruoyi·知识库·rag