您的位置:首页 > 数据库 > Redis

Linux下C++操作redis简述

2016-11-13 11:30 351 查看
Redis是基于内存的高性能key-value存储系统,是在实际项目中常用来作为缓存,队列,数据库来使用。本文主要介绍在Linux环境下如何使用C++作为客户端操作Redis。

C++中使用redis需要包含以下头文件

#include <hiredis/hiredis.h>


下面将从建立redis链接的对象redisContext和执行redis命令的返回对象redisReply说起。让我们从源码hiredis/hiredis.h开始吧。

redisContext是建立redis链接返回的上下文信息

typedef struct redisContext
{
int err; //链接错误的标志位,当正确链接时,该值为0
char errstr[128]; //链接错误时的错误描述
int fd; //正确链接时,返回的句柄,用于以后的命令执行等
int flags; //状态位 如REDIS_BLOCK...
char *obuf; //写缓冲区
//协议解析的状态,具体见redisReader定义,由于建立链接的协议解析是内部进行的
//没有暴露给外部使用,在此,不进行累述
redisReader *reader;
} redisContext;


当建立链接后,我们可以借助redisContext信息,判断链接是否成功了,以及实时监测当前的链接状态。

redis建立链接的方式有多种:

redisContext *redisConnect(const char *ip, int port);
redisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv);
redisContext *redisConnectNonBlock(const char *ip, int port);
redisContext *redisConnectBindNonBlock(const char *ip, int port, const char *source_addr);
.....


常见的链接方式是前两种,redisConnectWithTimeout()相对于redisConnect()提供超时链接功能。

struct timeval 定义在

#include <sys/time.h>


提供了微秒级的精度的时间操作。

struct timeval
{
time_t tv_sec; //秒
suseconds_t tv_usec;//微秒
};


redisReply,redis命令执行后的返回对象

typedef struct redisReply
{
/*
*返回值的类型
*#define REDIS_REPLY_STRING 1
*#define REDIS_REPLY_ARRAY 2
*#define REDIS_REPLY_INTEGER 3
*#define REDIS_REPLY_NIL 4
*#define REDIS_REPLY_STATUS 5
*#define REDIS_REPLY_ERROR 6
*/
int type; //返回值的类型
long long integer;  //当返回值是整数时,对应的整数值
int len;   //返回string值时,string值的长度
/*
*当返回类型是REDIS_REPLY_ERROR时,str是error的内容
*但返回类型是REDIS_REPLY_STRING时,str是string值的内容
*/
char *str;
//当返回类型是 REDIS_REPLY_ARRAY时,返回值的个数
size_t elements;
//当返回类型是 REDIS_REPLY_ARRAY时,对应的返回值‘数组’
struct redisReply **element;
} redisReply;


根据redis是C编写的,内存构造都是通过C的方式,由redisReply数据结构也可看出,每次执行命令后,不会自动析构返回值对象,我们应该及时的使用freeReplyObject释放对象,以免对下次执行结果造成影响。

此外,redisReply对象的返回值类型type是什么,取决于执行的命令,如果不知道,不妨通过shell执行下该命令,观察下状态

例如,当获取一个不存在的键值时,返回nil
127.0.0.1:6379> GET noexists
(nil)
当正确向有序集合加入键值对时,返回正确插入DB中的键值对个数
127.0.0.1:6379> ZADD students 16 Lilei
(integer) 1
当正确从string类型取值时,返回的是string
127.0.0.1:6379> get name
"Xiaoming"
...


C++执行redis语句的方式

void *redisvCommand(redisContext *c, const char *format, va_list ap);
void *redisCommand(redisContext *c, const char *format, ...);
具体将在示例中予以演示


下面以一个简单的示例,回顾下以上所述吧,本文redis版本为3.2.4,编译环境为“CentOS release 5.5 (Final)”。

#include <iostream>
#include <string>
//for C++ redis
#include <hiredis/hiredis.h>

using namespace std;

int main()
{
//使用本地地址和默认端口号
string strHost = "127.0.0.1";
int nPort = 6379;
//connect
redisContext *connect;
connect = redisConnect(strHost.c_str(),nPort);
if(NULL == connect)
{
cout<<__LINE__<<"Connect failed..."<<endl;
return -1;
}
//进一步检查连接的状态
if(connect->err)
{
//connect->errstr错误描述
cout<<__LINE__<<"Connect err"<<connect->errstr<<endl;
redisFree(connect);
return -1;
}
//向redis写入数据
//使用有序集合,向其中加入 姓名-年龄的键值对
redisReply *reply;
//方式一
string strcmd = "ZADD students 16 Lilei";
reply = (redisReply *) redisCommand(connect, strcmd.c_str());
if(NULL == reply)
{
cout<<__LINE__<<"Write to redis failed..."<<endl;
return -1;
}
//如正确执行,返回值类型应为成功插入数据库键值对个数,是一个整数
if(REDIS_REPLY_INTEGER != reply->type)
{
cout<<__LINE__<<"Execute failed..."<<endl;
freeReplyObject(reply);
return -1;
}
//释放上次执行的结果
freeReplyObject(reply);
//方式二
reply = (redisReply *) redisCommand(connect, "ZADD %s %d %s","students",15,"Hanmeimei");
if(NULL == reply)
{
cout<<__LINE__<<"Write to redis failed..."<<endl;
return -1;
}
//如正确执行,返回值类型应为成功插入数据库键值对个数,是一个整数
if(REDIS_REPLY_INTEGER != reply->type)
{
cout<<__LINE__<<"Execute failed..."<<endl;
freeReplyObject(reply);
return -1;
}
//释放上次执行的结果
freeReplyObject(reply);

//查询
strcmd = "ZRANGE students 0 -1 WITHSCORES";
reply = (redisReply *) redisCommand(connect, strcmd.c_str());
if(NULL == reply)
{
cout<<__LINE__<<"Write to redis failed..."<<endl;
return -1;
}
for(size_t i = 0 ; i < reply->elements ;++i)
{
//为什么是如下的输出方式,动手通过shell执行下 ZRANGE students 0 -1 WITHSCORES 吧
//实际上其返回值是
/*
127.0.0.1:6379> ZRANGE students 0 -1 WITHSCORES
1) "Hanmeimei"
2) "15"
3) "Lilei"
4) "16"
*/
string name = reply->element[i]->str ;
string age = reply->element[++i]->str ;

cout<<name<<":"<<age<<endl;
}
freeReplyObject(reply);

redisFree(connect);
return 0;
}


编译时请链接所需的库libhiredis,执行:

[root@localhost redis]# ./run

Hanmeimei:15

Lilei:16
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: