Hiredis GitHub地址:https://github.com/redis/hiredis
通过MAKEFILE编译安装,生成两个libhiredis.a libhiredis.so两个库文件,我们只要在我们的程序包含hiredis.h的头文件,在程序连接的时候连接-lhiredis就可以了。
hiredis的官方文档说明:http://blog.csdn.net/superinzaghi747/article/details/72725409里已经对hiredis的使用有了比较全面的介绍.这里对一些关键点做一些个人的理解说明:
两个结构:
1.维持与Redis连接的结构redisContex.
typedef struct redisContext {
int err; /* Error flags, 0 when there is no error */
char errstr[128]; /* String representation of error when applicable */
int fd;
int flags;
char *obuf; /* Write buffer */
redisReader *reader; /* Protocol reader */
enum redisConnectionType connection_type;
struct timeval *timeout;
struct {
char *host;
char *source_addr;
int port;
} tcp;
struct {
char *path;
} unix_sock;
} redisContext;
redisContext结构维护着一个与redis服务器的连接状态(在调用connect系列的函数后被初始化),其成员变量err为0时表示连接是正常的,非0值表示了有错误发生:
#define REDIS_ERR_IO 1 /* Error in read or write */
#define REDIS_ERR_EOF 3 /* End of file */
#define REDIS_ERR_PROTOCOL 4 /* Protocol error */
#define REDIS_ERR_OOM 5 /* Out of memory */
#define REDIS_ERR_OTHER 2 /* Everything else... */
此时可以通过errstr查看错误的原因.连接内部是TCP实现的,fd标识了socket连接描述符,struct tcp存储了连接的源地址ip,port信息.当执行redis命令失败后,这个结构指示的连接将不能再用,必须创建新的连接.该结构内存释放调用redisFree(...)函数.
2.执行redis命令后的结果:redisReply
/* This is the reply object returned by redisCommand() */
typedef struct redisReply {
int type; /* REDIS_REPLY_* */
long long integer; /* The integer when type is REDIS_REPLY_INTEGER */
size_t len; /* Length of string */
char *str; /* Used for both REDIS_REPLY_ERROR and REDIS_REPLY_STRING */
size_t elements; /* number of elements, for REDIS_REPLY_ARRAY */
struct redisReply **element; /* elements vector for REDIS_REPLY_ARRAY */
} redisReply;
执行不同类型的redis命令会返回不同的type.而根据type的不同,这个结构中有用的内容也会不同.在执行完一个redis命令后,我们将执行函数返回的void*指针转换为redisReply结构指针.首先判断此指针是否为null,如果为null,肯定是有错误发生了,这时保持连接的结构redisContext不能再用,可以看看这个结构的errstr到底是什么错误.
一共有6种类型的type.
#define REDIS_REPLY_STRING 1
当执行获取类型的命令:比如get,pop等时,会是此类型.此时通过获取str变量获取值.
#define REDIS_REPLY_ARRAY 2
当执行获取类型的命令返回的结果是多个时:比如lindex,smembers时,会是此类型.此时elements标识返回的元素个数,**element是一个redisReply的数组,每个元素对应一个返回的元素.
#define REDIS_REPLY_INTEGER 3
当执行add,hdel,hset等命令返回的结果是此类型,此时interger表示了执行的情况.
#define REDIS_REPLY_NIL 4
当执行命令后返回的结果为null时是此类型,此类型和1REDIS_REPLY_STRING类型一般同时判断,多个命令返回的类型是这两种中的一种.
#define REDIS_REPLY_STATUS 5
执行集合命令添加命令set,返回此类型.成功时str字段为OK.
#define REDIS_REPLY_ERROR 6
命令执行失败时,如果不是前面5中类型,就是此类型。str变量指示错误的原因.
每次获取到返回的redisReply结构指针使用完毕后,记得调用void freeReplyObject(void *reply)函数释放内存,否则会造成内存泄漏.这个指针为NULL也是可以调用次函数释放内存的,所以再使用完此结构后,无论这个结构的值是否为空,统一调用释放函数是好的习惯.对于ARRAY类型的reply结构指针不必嵌套调用,freeReplyObject函数内部已经实现:
case REDIS_REPLY_ARRAY:
if (r->element != NULL) {
for (j = 0; j < r->elements; j++)
if (r->element[j] != NULL)
freeReplyObject(r->element[j]);
free(r->element);
}
本人利用hiredis封装了一个简单的操作redis的C++类,实现了redis五种数据类型的一些基本操作.具体实现和说明请参照github地址:https://github.com/inzaghibest/CMyRedis