博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Redisclient连接方式Hiredis简单封装使用,连接池、屏蔽连接细节
阅读量:7181 次
发布时间:2019-06-29

本文共 4863 字,大约阅读时间需要 16 分钟。

工作须要对Hiredis进行了简单封装,实现功能:

1、API进行统一,对外仅仅提供一个接口。

2、屏蔽上层应用对连接的细节处理;

3、底层採用队列的方式保持连接池,保存连接会话。

4、重连时採用时间戳进行控制,每隔一定时间(3s)重连一次。防止频繁重试造成的不必要浪费。

先看一下Hiredis的经常使用数据结构与API:

//hiredis/hiredis.h/* Context for a connection to Redis */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 */} redisContext;/* This is the reply object returned by redisCommand() */#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 6typedef struct redisReply {    int type; /* REDIS_REPLY_* */    long long integer; /* The integer when type is REDIS_REPLY_INTEGER */    int 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;redisContext *redisConnectWithTimeout(const char *ip, int port, struct timeval tv);void redisFree(redisContext *c);

以下直接上封装后的代码:

class KGRedisClient{public:    KGRedisClient(string ip, int port, int timeout = 2000);    virtual ~KGRedisClient();    bool ExecuteCmd(const char *cmd, size_t len, string &response);    redisReply* ExecuteCmd(const char *cmd, size_t len);private:    int m_timeout;    int m_serverPort;    string m_setverIp;    CCriticalSection m_lock;    std::queue
m_clients; time_t m_beginInvalidTime; static const int m_maxReconnectInterval = 3; redisContext* CreateContext(); void ReleaseContext(redisContext *ctx, bool active); bool CheckStatus(redisContext *ctx);};KGRedisClient::KGRedisClient(string ip, int port, int timeout){ m_timeout = timeout; m_serverPort = port; m_setverIp = ip; m_beginInvalidTime = 0;}KGRedisClient::~KGRedisClient(){ CAutoLock autolock(m_lock); while(!m_clients.empty()) { redisContext *ctx = m_clients.front(); redisFree(ctx); m_clients.pop(); }}bool KGRedisClient::ExecuteCmd(const char *cmd, size_t len,string &response){ redisReply *reply = ExecuteCmd(cmd, len); if(reply == NULL) return false; boost::shared_ptr
autoFree(reply, freeReplyObject); if(reply->type == REDIS_REPLY_INTEGER) { response = _IntToStrA(reply->integer); return true; } else if(reply->type == REDIS_REPLY_STRING) { response.assign(reply->str, reply->len); return true; } else if(reply->type == REDIS_REPLY_STATUS) { response.assign(reply->str, reply->len); return true; } else if(reply->type == REDIS_REPLY_NIL) { response = ""; return true; } else if(reply->type == REDIS_REPLY_ERROR) { response.assign(reply->str, reply->len); return false; } else if(reply->type == REDIS_REPLY_ARRAY) { response = "Not Support Array Result!!!"; return false; } else { response = "Undefine Reply Type"; return false; }}redisReply* KGRedisClient::ExecuteCmd(const char *cmd, size_t len){ redisContext *ctx = CreateContext(); if(ctx == NULL) return NULL; redisReply *reply = (redisReply*)redisCommand(ctx, "%b", cmd, len); ReleaseContext(ctx, reply != NULL); return reply;}redisContext* KGRedisClient::CreateContext(){ { CAutoLock autolock(m_lock); if(!m_clients.empty()) { redisContext *ctx = m_clients.front(); m_clients.pop(); return ctx; } } time_t now = time(NULL); if(now < m_beginInvalidTime + m_maxReconnectInterval) return NULL; struct timeval tv; tv.tv_sec = m_timeout / 1000; tv.tv_usec = (m_timeout % 1000) * 1000;; redisContext *ctx = redisConnectWithTimeout(m_setverIp.c_str(), m_serverPort, tv); if(ctx == NULL || ctx->err != 0) { if(ctx != NULL) redisFree(ctx); m_beginInvalidTime = time(NULL); return NULL; } return ctx;}void KGRedisClient::ReleaseContext(redisContext *ctx, bool active){ if(ctx == NULL) return; if(!active) {redisFree(ctx); return;} CAutoLock autolock(m_lock); m_clients.push(ctx);}bool KGRedisClient::CheckStatus(redisContext *ctx){ redisReply *reply = (redisReply*)redisCommand(ctx, "ping"); if(reply == NULL) return false; boost::shared_ptr
autoFree(reply, freeReplyObject); if(reply->type != REDIS_REPLY_STATUS) return false; if(strcasecmp(reply->str,"PONG") != 0) return false; return true;}

稍加解释:

成员变量:m_clients用于保存连接池。

成员变量:m_beginInvalidTime、m_maxReconnectInterval 用于控制断掉时的频繁连接。

对外API:ExecuteCmd(const char *cmd, string &response);

转载地址:http://eoukm.baihongyu.com/

你可能感兴趣的文章
Struts2+Hibernate+Spring+Maven3整合(-)
查看>>
环境变量的4种配置方法
查看>>
跨域访问机制和应用程序域
查看>>
Linux
查看>>
我的友情链接
查看>>
linux 文件归档
查看>>
成为Linux大神计划书
查看>>
jmeter压测网站
查看>>
Windows Server 2012正式版RDS系列⑿
查看>>
aix iostat and vmstat
查看>>
网络工具 Netcat 之端口扫描
查看>>
参观迅达云成公司观后感
查看>>
如何在一台服务器上实现多个Web站点
查看>>
ubantu16.04安装配置samba服务(原创)
查看>>
DB2数据库代码页和实例代码页的区别(解决DB2乱码问题)
查看>>
结合超声计数炎症关节的改良版DAS28的临床应用
查看>>
如何用BarTender 2016字处理器完成表格设计
查看>>
JSON数据格式
查看>>
页面引入(include)方式的研究及性能比较
查看>>
文件操作
查看>>