Redis客户端连接方式Hiredis简单封装使用,连接池、屏蔽连接细节

转:https://blog.csdn.net/gdutliuyun827/article/details/44339007


对Hiredis进行了简单封装,实现功能:

1、API进行统一,对外只提供一个接口;

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

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

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

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

[cpp]  view plain  copy
  1. //hiredis/hiredis.h  
  2. /* Context for a connection to Redis */  
  3. typedef struct redisContext {  
  4.     int err; /* Error flags, 0 when there is no error */  
  5.     char errstr[128]; /* String representation of error when applicable */  
  6.     int fd;   
  7.     int flags;  
  8.     char *obuf; /* Write buffer */  
  9.     redisReader *reader; /* Protocol reader */  
  10. } redisContext;  
  11.   
  12. /* This is the reply object returned by redisCommand() */  
  13. #define REDIS_REPLY_STRING 1  
  14. #define REDIS_REPLY_ARRAY 2  
  15. #define REDIS_REPLY_INTEGER 3  
  16. #define REDIS_REPLY_NIL 4  
  17. #define REDIS_REPLY_STATUS 5  
  18. #define REDIS_REPLY_ERROR 6  
  19. typedef struct redisReply {  
  20.     int type; /* REDIS_REPLY_* */  
  21.     long long integer; /* The integer when type is REDIS_REPLY_INTEGER */  
  22.     int len; /* Length of string */  
  23.     char *str; /* Used for both REDIS_REPLY_ERROR and REDIS_REPLY_STRING */  
  24.     size_t elements; /* number of elements, for REDIS_REPLY_ARRAY */  
  25.     struct redisReply **element; /* elements vector for REDIS_REPLY_ARRAY */  
  26. } redisReply;  
  27.   
  28. redisContext *redisConnectWithTimeout(const char *ip, int port, struct timeval tv);  
  29. void redisFree(redisContext *c);  

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

[cpp]  view plain  copy
  1. class KGRedisClient  
  2. {  
  3. public:  
  4.     KGRedisClient(string ip, int port, int timeout = 2000);  
  5.     virtual ~KGRedisClient();  
  6.   
  7.     bool ExecuteCmd(const char *cmd, size_t len, string &response);  
  8.     redisReply* ExecuteCmd(const char *cmd, size_t len);  
  9.   
  10. private:  
  11.     int m_timeout;  
  12.     int m_serverPort;  
  13.     string m_setverIp;  
  14.     CCriticalSection m_lock;  
  15.     std::queue<redisContext *> m_clients;  
  16.   
  17.     time_t m_beginInvalidTime;  
  18.     static const int m_maxReconnectInterval = 3;  
  19.   
  20.     redisContext* CreateContext();  
  21.     void ReleaseContext(redisContext *ctx, bool active);  
  22.     bool CheckStatus(redisContext *ctx);  
  23. };  
  24.   
  25. KGRedisClient::KGRedisClient(string ip, int port, int timeout)  
  26. {  
  27.     m_timeout = timeout;  
  28.     m_serverPort = port;  
  29.     m_setverIp = ip;  
  30.   
  31.     m_beginInvalidTime = 0;  
  32. }  
  33.   
  34. KGRedisClient::~KGRedisClient()  
  35. {  
  36.     CAutoLock autolock(m_lock);  
  37.     while(!m_clients.empty())  
  38.     {  
  39.         redisContext *ctx = m_clients.front();  
  40.         redisFree(ctx);  
  41.         m_clients.pop();  
  42.     }  
  43. }  
  44.   
  45. bool KGRedisClient::ExecuteCmd(const char *cmd, size_t len,string &response)  
  46. {  
  47.     redisReply *reply = ExecuteCmd(cmd, len);  
  48.     if(reply == NULL) return false;  
  49.   
  50.     boost::shared_ptr<redisReply> autoFree(reply, freeReplyObject);  
  51.     if(reply->type == REDIS_REPLY_INTEGER)  
  52.     {  
  53.         response = _IntToStrA(reply->integer);  
  54.         return true;  
  55.     }  
  56.     else if(reply->type == REDIS_REPLY_STRING)  
  57.     {  
  58.         response.assign(reply->str, reply->len);  
  59.         return true;  
  60.     }  
  61.     else if(reply->type == REDIS_REPLY_STATUS)  
  62.     {  
  63.         response.assign(reply->str, reply->len);  
  64.         return true;  
  65.     }  
  66.     else if(reply->type == REDIS_REPLY_NIL)  
  67.     {  
  68.         response = "";  
  69.         return true;  
  70.     }  
  71.     else if(reply->type == REDIS_REPLY_ERROR)  
  72.     {  
  73.         response.assign(reply->str, reply->len);  
  74.         return false;  
  75.     }  
  76.     else if(reply->type == REDIS_REPLY_ARRAY)  
  77.     {  
  78.         response = "Not Support Array Result!!!";  
  79.         return false;  
  80.     }  
  81.     else  
  82.     {  
  83.         response = "Undefine Reply Type";  
  84.         return false;  
  85.     }  
  86. }  
  87.   
  88. redisReply* KGRedisClient::ExecuteCmd(const char *cmd, size_t len)  
  89. {  
  90.     redisContext *ctx = CreateContext();  
  91.     if(ctx == NULL) return NULL;  
  92.   
  93.     redisReply *reply = (redisReply*)redisCommand(ctx, "%b", cmd, len);  
  94.   
  95.     ReleaseContext(ctx, reply != NULL);  
  96.   
  97.     return reply;  
  98. }  
  99.   
  100. redisContext* KGRedisClient::CreateContext()  
  101. {  
  102.     {  
  103.         CAutoLock autolock(m_lock);  
  104.         if(!m_clients.empty())  
  105.         {  
  106.             redisContext *ctx = m_clients.front();  
  107.             m_clients.pop();  
  108.   
  109.             return ctx;  
  110.         }  
  111.     }  
  112.   
  113.     time_t now = time(NULL);  
  114.     if(now < m_beginInvalidTime + m_maxReconnectInterval) return NULL;  
  115.   
  116.     struct timeval tv;  
  117.     tv.tv_sec = m_timeout / 1000;  
  118.     tv.tv_usec = (m_timeout % 1000) * 1000;;  
  119.     redisContext *ctx = redisConnectWithTimeout(m_setverIp.c_str(), m_serverPort, tv);  
  120.     if(ctx == NULL || ctx->err != 0)  
  121.     {  
  122.         if(ctx != NULL) redisFree(ctx);  
  123.   
  124.         m_beginInvalidTime = time(NULL);  
  125.           
  126.         return NULL;  
  127.     }  
  128.   
  129.     return ctx;  
  130. }  
  131.   
  132. void KGRedisClient::ReleaseContext(redisContext *ctx, bool active)  
  133. {  
  134.     if(ctx == NULL) return;  
  135.     if(!active) {redisFree(ctx); return;}  
  136.   
  137.     CAutoLock autolock(m_lock);  
  138.     m_clients.push(ctx);  
  139. }  
  140.   
  141. bool KGRedisClient::CheckStatus(redisContext *ctx)  
  142. {  
  143.     redisReply *reply = (redisReply*)redisCommand(ctx, "ping");  
  144.     if(reply == NULL) return false;  
  145.   
  146.     boost::shared_ptr<redisReply> autoFree(reply, freeReplyObject);  
  147.   
  148.     if(reply->type != REDIS_REPLY_STATUS) return false;  
  149.     if(strcasecmp(reply->str,"PONG") != 0) return false;  
  150.   
  151.     return true;  
  152. }  

稍加解释:

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值