hiredis 是redis官方推荐的C/C++客户端库,笔者的使用场景是对二进制数据进行读写,初次使用有些需要格外注意的地方,可以称为踩过的小坑吧。
笔者使用hiredis 0.13.3, 对redis的读写操作进行了简单封装,以hash结构为例,代码片断如下:
bool RedisHandler::HGet(const string &name, const string &key, string &val) { for (int retry = 0; retry < MAX_RETRY_TIMES; ++ retry) { if (!connected && !Reconnect()) { continue; } redisReply *reply = (redisReply *) redisCommand(redis_context, "HGET %s %s", name.data(), key.data()); if (NULL == reply) { log(LOG_ERROR, "redis connection exception: %s\n", redis_context->errstr); connected = false; continue; } if (reply->type != REDIS_REPLY_STRING) { if (reply->type == REDIS_REPLY_ERROR) { log(LOG_ERROR, "redis HGet exception: %s\n", reply->str); } freeReplyObject(reply); return false; } val = string(reply->str, reply->len); freeReplyObject(reply); return true; } return false; } bool RedisHandler::HSet(const string &name, const string &key, const string &val) { for (int retry = 0; retry < MAX_RETRY_TIMES; ++ retry) { if (!connected && !Reconnect()) { continue; } redisReply *reply = (redisReply *) redisCommand(redis_context, "HSET %s %s %b", name.data(), key.data(), val.data(), val.size()); if (NULL == reply) { log(LOG_ERROR, "redis connection exception: %s\n", redis_context->errstr); connected = false; continue; } if (reply->type != REDIS_REPLY_INTEGER) { if (reply->type == REDIS_REPLY_ERROR) { log(LOG_ERROR, "redis HSet exception: %s\n", reply->str); } freeReplyObject(reply); return false; } freeReplyObject(reply); return true; } return false; }
对于二进制数据存取有如下两点需要注意:
1. 对于二进制(如thrift序列化后的数据)构造格式输入时,需使用”%b”, val.data(), val.size() 的形式;
2. 对于读取存储在redis内的二进制数据时, 对返回的string一定要通过string(reply->str, reply->len)构造返回,才能读取到完整的数据;
其实对于以上注意,hiredis官方文档也有明确说明,只是我们在写时没有注意或仔细查看了,原文如下:
When you need to pass binary safe strings in a command, the
%b
specifier can be used. Together with a pointer to the string, it requires asize_t
length argument of the string:reply = redisCommand(context, "SET foo %b", value, (size_t) valuelen);
Refer:
1 https://github.com/redis/hiredis
2 http://yaocoder.blog.51cto.com/2668309/1297031