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

redisAsyncConnect 启动后不触发回调?
异步连接没反应,多半是没跑 aeMain 或 redisAsyncHandleRead/redisAsyncHandleWrite。hiredis 的异步模式不自己起事件循环,得你手动把 socket 读写事件喂给它。
- 用
libEvent时,必须调redisLibeventAttach绑定 event_base,否则redisAsyncContext不知道往哪注册 fd - 纯 epoll/kqueue 自己轮询?得在每次就绪后显式调
redisAsyncHandleRead(ctx)和redisAsyncHandleWrite(ctx) - 忘记调
redisAsyncSetConnectCallback或redisAsyncSetDisconnectCallback—— 连接失败也不会报错,只是静默卡住
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 只在压测时出现。