hiredis php,redis 连接池 hiredis
对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相关推荐
- python redis连接池获取后关闭_python通过连接池连接redis,操作redis队列
在每次使用redis都进行连接的话会拉低redis的效率,都知道redis是基于内存的数据库,效率贼高,所以每次进行连接比真正使用消耗的资源和时间还多.所以为了节省资源,减少多次连接损耗,连接池的作用 ...
- Java的Redis连接池代码性能不错
其实这个是引用自网友http://blog.csdn.net/tuposky/article/details/45340183,有2个版本,差别就是ReentrantLock和synchronized ...
- redis连接池操作
/** * @类描述 redis 工具 * @功能名 POJO * @author zxf * @date 2014年11月25日 */ public final class RedisUtil { ...
- java操作redis redis连接池
redis作为缓存型数据库,越来越受到大家的欢迎,这里简单介绍一下java如何操作redis. 1.java连接redis java通过需要jedis的jar包获取Jedis连接. jedis-2.8 ...
- redis专题:redis键值设计、性能优化以及redis连接池配置
文章目录 1.redis键值设计 ①:key设计规范 ②:value设计规范 2. 命令使用优化 3. redis连接池配置参数设计 4. redis连接池预热 5. redis的key过期删除策略 ...
- Java Redis 连接池 Jedis 工具类,java基础面试笔试题
我总结出了很多互联网公司的面试题及答案,并整理成了文档,以及各种学习的进阶学习资料,免费分享给大家. 扫描二维码或搜索下图红色VX号,加VX好友,拉你进[程序员面试学习交流群]免费领取.也欢迎各位一起 ...
- Java的Redis连接池代码
2019独角兽企业重金招聘Python工程师标准>>> 其实这个是引用自网友http://blog.csdn.net/tuposky/article/details/45340183 ...
- php redis 集群 长连接池,php如何实现redis连接池
项目使用的是php,生产环境使用的是redis集群,连接的地址是配置的域名,每次创建连接必须要经过一次域名解析,频繁的创建链接效率低下且经常出现超时的情况,有没有在生产环境实现redis链接池的,分享 ...
- SpringBoot 配置 Redis 连接池
前言 SpringBoot2.0默认采用 Lettuce 客户端来连接 Redis 服务 默认是不使用连接池的,只有配置 redis.lettuce.pool下的属性的时候才可以使用到redis连接池 ...
最新文章
- grep及正则表达式
- php代码审计工具_【学习笔记】PHP代码审计入门:代码审计实例2
- C指针原理(8)-C内嵌汇编
- python处理windows弹窗_Python窗口IDE的基本处理,pythonwindowide
- 【C、C++基础】什么时候用 “.” 什么时候用“->”(3个实例搞懂)
- speech模块实现语音识别
- k8s查看pod的yaml文件_K8s-yaml的使用及命令
- mysql中使用正则表达式,mysql中使用正则表达式查询
- 数据可视化之多属性(字段)
- 2020年上半年,谷歌共检测到11个已遭利用的 0day
- 关注Linux防火墙之介绍iptables与ufw命令
- 还原mysql数据库出错_mysql数据库还原出错ERROR:Unknown command ‘\\’解决手记
- 安平仓管王 3000xp v3.2 免费下载
- 火星坐标系解密-iDesktopX空间数据处理
- c语言 程序设计一篇,用c语言编程任务br/请编写一个程序,从输入中读取一篇中文文 爱问知识人...
- 自动薅羊毛技术方案总结
- google aviator:轻量级Java公式引擎
- ur机器人计算机模拟仿真,UR机器人科研应用案例
- vue 快速入门指南(一)
- #第五章“拷问”既往的股市理论5.1有人情味的“拷问”
热门文章
- 基于SSM的网上餐厅管理系统
- ProxmoxVE 之 使用thinstation利旧安装瘦客户端
- 电子稳定器云台的校准
- 青蛙过河 C# 求解
- 电信黑莓手机出国漫游注意事项
- 支付宝正式发布黑莓版客户端
- CodeCraft-20 (Div. 2)(C(本原多项式) D (BFS) E (状压+dp))
- beautyEye输入框中文输入法白屏bug
- proteus如何添加stm32_电路仿真软件详谈(六),Proteus电路仿真软件的超级应用
- 华为硬件工程师手册_一名电子工程师该如何打开正确的摆摊姿势?