对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 6

typedef 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);

封装后的代码:

redis_pool.h

#ifndef __REDIS_POOL_H__

#define __REDIS_POOL_H__

#include

#include

#include

#include

#include

#include

#include

#include

#include "hiredis/hiredis.h"

class KGRedisClient

{

public:

KGRedisClient(std::string ip, int port, std::string password, int timeout = 2000);

virtual ~KGRedisClient();

//   bool ExecuteCmd_spop(const char *cmd, size_t len, std::string &response);

bool ExecuteCmd_spop(std::string &response, const char* format, ...);

//   redisReply* ExecuteCmd(const char *cmd, size_t len);

redisReply* ExecuteCmd(const char* format, ...);

private:

int m_timeout;

int m_serverPort;

std::string m_setverIp;

std::string m_password;

//   CCriticalSection m_lock;

std::mutex _mutex;

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);

};

#endif

redis_pool.cpp

#include "redis_pool.h"

#include

KGRedisClient::KGRedisClient(std::string ip, int port, std::string password, int timeout)

{

m_timeout = timeout;

m_serverPort = port;

m_setverIp = ip;

m_password = password;

m_beginInvalidTime = 0;

}

KGRedisClient::~KGRedisClient()

{

//    CAutoLock autolock(m_lock);

std::unique_lock <:mutex> lck(_mutex);

while(!m_clients.empty())

{

redisContext *ctx = m_clients.front();

redisFree(ctx);

m_clients.pop();

}

}

bool KGRedisClient::ExecuteCmd(std::string &response, const char* format, ...)

{

va_list args;

va_start(args, format);

redisReply *reply = ExecuteCmd(format, args);

va_end(args);

if(reply == NULL) return false;

std::shared_ptr autoFree(reply, freeReplyObject);

if(reply->type == REDIS_REPLY_INTEGER)

{

response = std::to_string(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* format, ...)

{

va_list args;

va_start(args, format);

redisContext *ctx = CreateContext();

if(ctx == NULL) return NULL;

//  redisReply *reply = (redisReply*)redisCommand(ctx, "spop %b", cmd, len);

//   redisReply *reply = (redisReply*)redisCommand(ctx, "%s", cmd);

redisReply* reply = (redisReply*)redisCommand(ctx, format, args);

va_end(args);

ReleaseContext(ctx, reply != NULL);

return reply;

}

redisContext* KGRedisClient::CreateContext()

{

{

//        CAutoLock autolock(m_lock);

std::unique_lock <:mutex> lck(_mutex);

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;

}

redisReply *reply;

std::string strReply = "AUTH ";

strReply += m_password;

reply = (redisReply*)redisCommand(ctx, strReply.c_str());

freeReplyObject(reply);

reply = NULL;

printf("connect OK\n");

return ctx;

}

void KGRedisClient::ReleaseContext(redisContext *ctx, bool active)

{

if(ctx == NULL) return;

if(!active) {redisFree(ctx); return;}

//    CAutoLock autolock(m_lock);

std::unique_lock <:mutex> lck(_mutex);

m_clients.push(ctx);

}

bool KGRedisClient::CheckStatus(redisContext *ctx)

{

redisReply *reply = (redisReply*)redisCommand(ctx, "ping");

if(reply == NULL) return false;

std::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);

hiredis php,redis 连接池 hiredis相关推荐

  1. python redis连接池获取后关闭_python通过连接池连接redis,操作redis队列

    在每次使用redis都进行连接的话会拉低redis的效率,都知道redis是基于内存的数据库,效率贼高,所以每次进行连接比真正使用消耗的资源和时间还多.所以为了节省资源,减少多次连接损耗,连接池的作用 ...

  2. Java的Redis连接池代码性能不错

    其实这个是引用自网友http://blog.csdn.net/tuposky/article/details/45340183,有2个版本,差别就是ReentrantLock和synchronized ...

  3. redis连接池操作

    /** * @类描述 redis 工具 * @功能名 POJO * @author zxf * @date 2014年11月25日 */ public final class RedisUtil { ...

  4. java操作redis redis连接池

    redis作为缓存型数据库,越来越受到大家的欢迎,这里简单介绍一下java如何操作redis. 1.java连接redis java通过需要jedis的jar包获取Jedis连接. jedis-2.8 ...

  5. redis专题:redis键值设计、性能优化以及redis连接池配置

    文章目录 1.redis键值设计 ①:key设计规范 ②:value设计规范 2. 命令使用优化 3. redis连接池配置参数设计 4. redis连接池预热 5. redis的key过期删除策略 ...

  6. Java Redis 连接池 Jedis 工具类,java基础面试笔试题

    我总结出了很多互联网公司的面试题及答案,并整理成了文档,以及各种学习的进阶学习资料,免费分享给大家. 扫描二维码或搜索下图红色VX号,加VX好友,拉你进[程序员面试学习交流群]免费领取.也欢迎各位一起 ...

  7. Java的Redis连接池代码

    2019独角兽企业重金招聘Python工程师标准>>> 其实这个是引用自网友http://blog.csdn.net/tuposky/article/details/45340183 ...

  8. php redis 集群 长连接池,php如何实现redis连接池

    项目使用的是php,生产环境使用的是redis集群,连接的地址是配置的域名,每次创建连接必须要经过一次域名解析,频繁的创建链接效率低下且经常出现超时的情况,有没有在生产环境实现redis链接池的,分享 ...

  9. SpringBoot 配置 Redis 连接池

    前言 SpringBoot2.0默认采用 Lettuce 客户端来连接 Redis 服务 默认是不使用连接池的,只有配置 redis.lettuce.pool下的属性的时候才可以使用到redis连接池 ...

最新文章

  1. grep及正则表达式
  2. php代码审计工具_【学习笔记】PHP代码审计入门:代码审计实例2
  3. C指针原理(8)-C内嵌汇编
  4. python处理windows弹窗_Python窗口IDE的基本处理,pythonwindowide
  5. 【C、C++基础】什么时候用 “.” 什么时候用“->”(3个实例搞懂)
  6. speech模块实现语音识别
  7. k8s查看pod的yaml文件_K8s-yaml的使用及命令
  8. mysql中使用正则表达式,mysql中使用正则表达式查询
  9. 数据可视化之多属性(字段)
  10. 2020年上半年,谷歌共检测到11个已遭利用的 0day
  11. 关注Linux防火墙之介绍iptables与ufw命令
  12. 还原mysql数据库出错_mysql数据库还原出错ERROR:Unknown command ‘\\’解决手记
  13. 安平仓管王 3000xp v3.2 免费下载
  14. 火星坐标系解密-iDesktopX空间数据处理
  15. c语言 程序设计一篇,用c语言编程任务br/请编写一个程序,从输入中读取一篇中文文 爱问知识人...
  16. 自动薅羊毛技术方案总结
  17. google aviator:轻量级Java公式引擎
  18. ur机器人计算机模拟仿真,UR机器人科研应用案例
  19. vue 快速入门指南(一)
  20. #第五章“拷问”既往的股市理论5.1有人情味的“拷问”

热门文章

  1. 基于SSM的网上餐厅管理系统
  2. ProxmoxVE 之 使用thinstation利旧安装瘦客户端
  3. 电子稳定器云台的校准
  4. 青蛙过河 C# 求解
  5. 电信黑莓手机出国漫游注意事项
  6. 支付宝正式发布黑莓版客户端
  7. CodeCraft-20 (Div. 2)(C(本原多项式) D (BFS) E (状压+dp))
  8. beautyEye输入框中文输入法白屏bug
  9. proteus如何添加stm32_电路仿真软件详谈(六),Proteus电路仿真软件的超级应用
  10. 华为硬件工程师手册_一名电子工程师该如何打开正确的摆摊姿势?