Linux下操作Redis类(基于hiredis接口)

选择Redis作为NoSql数据库的几点考虑:

  • 数据全部存储至内存中,相对操作数据库(写磁盘)而言读写速度快且支持并发量高
  • 支持持久化,AOF&RDB持久化机制可以避免由一些不可控因素导致的数据丢失问题(如:断电)
  • 二进制安全,可支持存储二进制数据(如:自定义的数据包结构体和图片等信息)
  • 支持数据类型多样,字符串、列表、集合、有序集合等对象可完全满足业务系统的数据存储要求
  • Redis3.0开始支持分布式集群,不用再使用twemproxy+redis组合来实现集群,安装配置简单,功能强大。

Redis中重要宏定义及结构体介绍:

  • struct redisContext结构体
/* redisConnect()函数返回结构体,代表该Redis的连接句柄 */
typedef struct redisContext {
    int err; /* Error flags, 0 when there is no error */
    char errstr[128]; /* String representation of error */
    int fd;
    int flags;
    char *obuf; /* Write buffer */
    redisReader *reader; /* Protocol reader */
} redisContext;
  • struct redisReply结构体
/* redisCommand()函数返回结构体,代表该Redis命令操作的返回结果,通过type成员变量处理此结构体*/
typedef struct redisReply {
    int type; 
    long long integer; 
    int len;
    char *str; 
    size_t elements;
    struct redisReply **element; 
} redisReply;

redisReply结构体处理方式如下截图:

  • struct redisReply::type 成员变量值宏定义:
    #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

hiredis接口中重要函数及功能介绍:

  • redisConnect 连接redis
  • redisConnectWithTimeout 连接redis,自定义超时时间
  • redisCommand redis命令执行函数
  • redisFree 释放连接redis资源(redisContext *)
  • freeReplyObject 释放redis执行函数返回的资源(redisReply *)

Talk is cheap, show me the code !!!

linkRedis.h

#ifndef __LINK_REDIS__
#define __LINK_REDIS__

#include 
#include 
#include 
#include 
#include 

using namespace std;

/*连接redis必须要的信息*/
struct LinkRedisInfo
{
    string ip;  
    unsigned short port;
    unsigned int timeOut;   //超时时间

    LinkRedisInfo(string ip_, unsigned short port_, unsigned int timeOut_):ip(ip_),\
           port(port_),timeOut(timeOut_){}
};

class LinkRedis
{
private:
    typedef map<string, pair > mp_redis;
    typedef map<string, pair >::iterator mp_redis_iter;

    mp_redis mp_link;
    map<string,string > mp_error_str;
public:
    LinkRedis();
    ~LinkRedis();

    //注册Redis连接
    bool RegisterLink(string name,string ip,unsigned short port,unsigned int timeOut);

    //连接Redis
    bool ConnectRedis();
    bool ConnectSingleRedis(string name);

    //Redis操作错误信息打印 
    void RedisError(string name);
    //Redis操作结果集同意处理函数
    int RedisReplyDeal(redisReply *pReply);

    //Redis命令执行函数(不支持二进制)
    redisReply* RedisExce(const char *name,const char *pCommand);
    //Redis命令执行函数(支持二进制)
    redisReply* RedisExceBinSafe(const char *name,const char *pCommand,char *pNode,unsigned int len);

    //Redis命令执行&结果导出函数(结果导出至int动态数组)
    bool RedisCommand2Int(const char *name,const char *pCommand,vector<int> *pVer);
    //Redis命令执行&结果导出函数(结果导出至string动态数组)
    bool RedisCommand2String(const char *name,const char *pCommand,vector<string> *pVer);
};
#endif

linkRedis.cpp

#include "linkRedis.h"

LinkRedis::LinkRedis()
{
}

//释放所有的连接资源
LinkRedis::~LinkRedis()
{
        for(mp_redis_iter it= mp_link.begin();it!= mp_link.end();it++)
        {
                if(it->second.second!= NULL)
                {
                        redisFree(it->second.second);
                }
                if(it->second.first!= NULL)
                {
                        delete it->second.first;
                }
        }
}

/*
 *@funs:                注册Redis连接信息
 *@param name:      自定义连接名
 *@param ip:        Redis IP地址
 *@param port:      Redis PORT端口
 *@param timeOut:    Redis连接超时时间
 *@ret:             true/注册成功   false/注册失败
 */
bool LinkRedis::RegisterLink(string name,string ip,unsigned short port,unsigned int timeOut)
{
        bool bRet= false;
        LinkRedisInfo *pInfo= new LinkRedisInfo(ip,port,timeOut);

        if(pInfo!= NULL)
        {
                mp_link[name].first= pInfo;
                mp_link[name].second= NULL;
                mp_error_str[name]= "";
                bRet= true;
        }
        return bRet;
}

/*
 *@funs:         连接name对应信息的Redis
 *@param name:   自定义连接名
 *@ret:          true/连接成功   false/连接失败
 */
bool LinkRedis::ConnectSingleRedis(string name)
{
        bool bRet= false;
        mp_redis_iter it= mp_link.find(name);

        if(it!= mp_link.end())
        {
                struct timeval tv;
                tv.tv_sec= it->second.first->timeOut;
                tv.tv_usec= 0;
                if(NULL!= (it->second.second= redisConnectWithTimeout(it->second.first->ip.c_str(),\
                                                it->second.first->port,tv)))
                {
                        bRet= true;
                }
        }
        return bRet;
}

/*
*@funs:         连接注册过的所有Redis信息
*@ret:          true/连接成功   false/连接失败
*/
bool LinkRedis::ConnectRedis()
{
    bool bRet= true;

    for(mp_redis_iter it= mp_link.begin();it!= mp_link.end();it++)
    {
        if(!ConnectSingleRedis(it->first))
        {
            bRet= false;
        }
    }
    return bRet;
}

void LinkRedis::RedisError(string name)
{
    map<string,string >::iterator it= mp_error_str.find(name);
    if(it!= mp_error_str.end())
    {
        cout<< it->second.c_str()<< endl;   
    }
}

/*
*@funs:     redis查询结果统一处理函数
*@param 1:  redisCommand函数返回结果
*@ret:      -1/reids操作错误 0/返回结果为空 >0/redis操作正常
*/
int LinkRedis::RedisReplyDeal(redisReply *pReply)
{
    int ret= -1;

    if(pReply!= NULL)
    {
        switch(pReply->type)
        {
            case REDIS_REPLY_NIL:
                ret= 0;
                break;

            case REDIS_REPLY_ERROR:
                ret= -1;
                break;

            default:
                ret= pReply->type;
                break;
        }
    }
    return ret;
}

/*
*@funs:     redis查询函数
*@param 1:  redis连接名
*@param 2:  redis Command操作指令
*@ret:      NULL/reids操作错误 非NULL/返回redis操作正常结果
*/
redisReply* LinkRedis::RedisExce(const char *name,const char *pCommand)
{
    redisReply* pReply= NULL;
    if(name!= NULL && pCommand!= NULL)
    {
        mp_redis_iter it= mp_link.find(name);

        if(it!= mp_link.end())
        {
            //执行command命令
            pReply =(redisReply*) redisCommand(it->second.second,pCommand); 
            if(pReply!= NULL)
            {
                //如果返回结果错误,则直接释放返回资源并记录错误信息
                if(RedisReplyDeal(pReply)< 0)
                {
                    //释放出错的操作结果集
                    freeReplyObject(pReply);
                    mp_error_str[name]= pReply->str;
                    mp_error_str[name].append(pCommand);
                    pReply= NULL;
                }   
            }
        }
    }
    return pReply;
}

/*
*@funs:     redis二进制安全查询函数
*@param 1:  redis连接名
*@param 2:  redis Command操作指令
*@param 3:  二进制数据存储数组
*@param 4:  二进制数据长度
*@ret:      NULL/reids操作错误 非NULL/返回redis操作正常结果
*/
redisReply* LinkRedis::RedisExceBinSafe(const char *name,const char *pCommand,char *pNode,unsigned int len)
{
    redisReply* pReply= NULL;

    if(name!= NULL && pCommand!= NULL && pNode!= NULL && len> 0)
    {
        mp_redis_iter it= mp_link.find(name);
        if(it!= mp_link.end())
        {
            pReply =(redisReply*) redisCommand(it->second.second,pCommand,pNode,len);   
            if(pReply!= NULL)
            {
                //如果返回结果错误,则直接释放返回资源并记录错误信息
                if(RedisReplyDeal(pReply)< 0)
                {
                    //释放出错的操作结果集
                    freeReplyObject(pReply);
                    mp_error_str[name]= pReply->str;
                    mp_error_str[name].append(pCommand);
                    pReply= NULL;
                }   
            }
        }
    }
    return pReply;
}

/*
*@funs:     redis查询&结果导出函数
*@param 1:  redis连接名
*@param 2:  redis Command操作指令
*@param 3:  redis Command操作结果存放地址
*@ret:      true/reids操作成功 false/redis操作失败
*/
bool LinkRedis::RedisCommand2Int(const char *name,const char *pCommand,vector<int> *pVer)
{
    bool bRet= false;

    if(pVer!= NULL && name!= NULL && pCommand!= NULL)
    {
        redisReply* pReply= RedisExce(name,pCommand);
        if(pReply== NULL)
        {
            return bRet;
        }

        //如果返回单个数值,则直接放至动态数组
        if(pReply->type== REDIS_REPLY_INTEGER)
        {
            pVer->push_back(pReply->integer);   
            bRet= true;
        }
        else if(pReply->type== REDIS_REPLY_ARRAY)
        {
            redisReply* pTmp= NULL;
            //如果返回数组,则取出每个数组中值并存放至动态数组
            for(int i= 0;i< pReply->elements;i++)
            {
                pTmp= pReply->element[i];
                if(RedisReplyDeal(pTmp)> 0 && pTmp->type== REDIS_REPLY_INTEGER)
                {
                    pVer->push_back(pTmp->integer);
                    freeReplyObject(pTmp);
                }
                else
                {
                    continue;
                }
            }
            if(pVer->size()== pReply->elements)
                bRet= true;
        }
        freeReplyObject(pReply);
    }
    return bRet;
}

/*
*@funs:     redis查询&结果导出函数
*@param 1:  redis连接名
*@param 2:  redis Command操作指令
*@param 3:  redis Command操作结果存放地址
*@ret:      true/reids操作成功 false/redis操作失败
*/
bool LinkRedis::RedisCommand2String(const char *name,const char *pCommand,vector<string> *pVer)
{
    bool bRet= false;

    if(pVer!= NULL && name!= NULL && pCommand!= NULL)
    {
        redisReply* pReply= RedisExce(name,pCommand);
        if(pReply== NULL)
        {
            return bRet;
        }

        if(pReply->type== REDIS_REPLY_STRING)
        {
            pVer->push_back(pReply->str);   
            bRet= true;
        }
        else if(pReply->type== REDIS_REPLY_ARRAY)
        {
            redisReply* pTmp= NULL;
            for(int i= 0;i< pReply->elements;i++)
            {
                pTmp= pReply->element[i];
                if(RedisReplyDeal(pTmp)> 0 && pTmp->type== REDIS_REPLY_STRING)
                {
                    pVer->push_back(pTmp->str);
                    freeReplyObject(pTmp);
                }
                else
                {
                    continue;
                }
            }
            if(pVer->size()== pReply->elements)
                bRet= true;
        }
        freeReplyObject(pReply);
    }
    return bRet;
}

示例程序:main.cpp

#include "linkRedis.h"
#include 
#include 
#include 


int main()
{
    using namespace std;
    LinkRedis test;
    vector<string> info;

    string name= "test1";
    string ip= "172.16.4.70";
    unsigned short= 7000;
    int timeOut= 5;

    test.RegisterLink(name,ip,port,timeOut);

    //连接redis
    if(test.ConnectRedis())
    {
        //执行redis命令,并将返回结果存储至动态字符串数组中
        if(test.RedisCommand2String(name.c_str(),"hget 31196:3  Ip",&info))
        {
            for(int i= 0;i< info.size();i++)
            {
                cout<< info[i].c_str()<< endl;
            }
        }
        else
        {

            test.RedisError(name);
        }
    }
    else
    {
        cout<< "error !"<< endl;
    }
    return 1;
}

编译:g++ main.cpp linkRedis.cpp -o main -lhiredis

以上代码仅为个人愚见,如有疑问请各位看官指出。tks

你可能感兴趣的:(common,linux类)