C++怎么连接Redis_C++客户端库使用教程【存储】

1次阅读

redisasyncconnect不触发回调,主因未运行事件循环或未调用读写处理函数;中文/二进制数据需用%b格式和utf-8编码;reply->str可能为空;异步断开需等待完成;redisasynccontext非线程安全。

C++怎么连接Redis_C++客户端库使用教程【存储】

redisAsyncConnect 启动后不触发回调?

异步连接没反应,多半是没跑 aeMainredisAsyncHandleRead/redisAsyncHandleWrite。hiredis 的异步模式不自己起事件循环,得你手动把 socket 读写事件喂给它。

  • libEvent 时,必须调 redisLibeventAttach 绑定 event_base,否则 redisAsyncContext 不知道往哪注册 fd
  • 纯 epoll/kqueue 自己轮询?得在每次就绪后显式调 redisAsyncHandleRead(ctx)redisAsyncHandleWrite(ctx)
  • 忘记调 redisAsyncSetConnectCallbackredisAsyncSetDisconnectCallback —— 连接失败也不会报错,只是静默卡住

set 命令传中文或二进制数据总乱码?

hiredis 默认把 redisReply 当 C 字符串处理,遇到 或非 UTF-8 字节就截断。Redis 本身不关心编码,但客户端解析时会崩。

  • 写二进制数据(比如 protobuf 序列化结果),别用 redisCommand(ctx, "SET %s %s", key, val) —— %s 遇到 就停。改用 redisCommand(ctx, "SET %s %b", key, val, len)%b 才支持长度+指针
  • key 本身含非 ASCII 字符?确保编译时源文件编码为 UTF-8,且字符串字面量用 u8"中文" 前缀(c++11 起)
  • 读回来的 reply->str 可能为 nullptr(比如返回整数或空值),别直接 printf("%s", reply->str)

程序退出时 redisAsyncDisconnect 不生效?

调了 redisAsyncDisconnect,但 Redis 服务端 still sees the client connected —— 因为这只是发 FIN,没等对方 ACK 就 exit 了。

  • 必须在 redisAsyncDisconnect 后调 aeMain 等待断开完成,或者加超时等待:用 redisPolling 循环检查 ctx->err 是否变为 REDIS_ERR_IO
  • 更稳妥的做法:先 redisAsyncDisconnect,再调 redisFreeAsyncContext,但注意此时 context 已不可再用,别在回调里访问它
  • 如果用 RAII 封装析构函数里别直接 free context —— 异步上下文销毁需配合事件循环,否则可能 crash

多线程环境下 redisAsyncContext 安全吗?

不安全。redisAsyncContext 内部状态(比如 pending command 队列、socket fd)不是线程安全的,多个线程同时调 redisAsyncCommand 会破坏链表或覆盖 callback 指针。

立即学习C++免费学习笔记(深入)”;

  • 一个 redisAsyncContext 只能由一个线程驱动事件循环(即只在一个线程里调 redisAsyncHandleRead 等)
  • 需要并发写入?要么用多个 context + 多个 event loop(每个线程一个),要么用同步接口 redisCommand + 连接池
  • 千万别在线程 A 调 redisAsyncCommand,在线程 B 的 event loop 里处理 —— hiredis 不保证跨线程 callback 调度

异步客户端最易被忽略的点:它根本不管你的线程模型,也不替你管资源生命周期。context、event base、callback 函数对象三者谁先销毁、谁持有谁,得自己画清楚引用关系,不然 core dump 只在压测时出现。

text=ZqhQzanResources