hiredis的异步接口已经支持ae libuv libev 和 libevent集成,具体头文件可以参见redis/deps/hiredis/adapters,样例参见redis/deps/hiredis/examples.

完整样例参见: https://github.com/DavadDi/study_example/tree/master/async_redis_client

参照hireids的异步接口和libevent的集成可以很容易和其他网络框架集成,例如asio或者ace等。 以下样例为自己编写reactor框架的集成方式,

支持自动重练和asyncRedisContext对象的创建和释放,重练使用退步算法,最大连接时间间隔为32秒。

使用方式:
  将redis_client.hpp 放到 hiredis的adapter目录即可。

 #ifndef redis_client_h
#define redis_client_h #include "reactor/define.hpp"
#include "reactor/event_handler.hpp"
#include "hiredis.h"
#include "async.h" using namespace reactor; static void redisReactorAddRead(void *arg);
static void redisReactorDelRead(void *arg);
static void redisReactorAddWrite(void *arg);
static void redisReactorDelWrite(void *arg);
static void redisReactorCleanup(void *arg); void connectCallBack(const redisAsyncContext *c, int status);
void disconnectCallBack(const redisAsyncContext *c, int status); void get_call_fun(redisAsyncContext *c, void *r, void *arg)
{
redisReply *reply = (redisReply *)r;
std::string *key_str = (std::string *)arg; if (reply == NULL)
{
delete key_str;
return;
} LOG_INFO("[%s] -> %s\n", key_str->c_str(), reply->str); delete key_str; /* Disconnect after receiving the reply to GET */
// redisAsyncDisconnect(c);
} // -------------------------------------------------------------------
// !!NOTE, if obj conneted to server faild and unregister from epoll,
// prog exit, this object my leak memory
// ------------------------------------------------------------------- class CRedisClient : public CEventHandler
{
public:
// enum {MAX_BUF_SIZE = 4096};
typedef CEventHandler super; CRedisClient(const char *srv_ip, uint16_t srv_port, reactor::CReactor *reactor)
: super(reactor)
{
m_srv_ip_str = srv_ip;
m_srv_port = srv_port;
} int connect()
{
LOG_DEBUG("Enter CRedisClient connect()");
m_client_status = CONNECT_STATUS::CLIENT_CONNECTING; clear_redis_context(); m_redis_context = redisAsyncConnect(m_srv_ip_str.c_str(), m_srv_port);
if (m_redis_context == nullptr)
{
return -;
} if (m_redis_context->err)
{
LOG_INFO("Connect to %s:%d Error: %s",
m_srv_ip_str.c_str(), m_srv_port, m_redis_context->errstr); return -;
} if (m_timer_id == )
{
m_timer_id = this->reactor()->regist_timer(this, m_timeout_value); // only one time
LOG_DEBUG("Client regist timer to reactor id %d, timeout %d", m_timer_id, m_timeout_value);
} this->attach(); return ;
} virtual ~CRedisClient()
{
// maybe should not free redis context in deconstuct!!
m_delete_redis_context = true;
clear_redis_context();
} virtual int open(void *data = nullptr)
{
m_client_status = CONNECT_STATUS::CLIENT_CONNECTED; m_delete_redis_context = false; if (m_timer_id == )
{
m_timer_id = this->reactor()->regist_timer(this, m_timeout_value); // only one time
LOG_DEBUG("Client regist timer to reactor id %d, timeout %d",
m_timer_id, m_timeout_value);
} LOG_INFO("Connect to RedisServer %s:%d succeed!!",
m_srv_ip_str.c_str(), m_srv_port); return ;
} virtual int handle_input(socket_t socket)
{
redisAsyncHandleRead(m_redis_context);
return ;
} virtual int handle_output(socket_t socket)
{
redisAsyncHandleWrite(m_redis_context);
return ;
} virtual int handle_timeout(uint32_t tm, void *data = nullptr)
{
// LOG_DEBUG("Enter into timeout function....");
if (m_client_status == CONNECT_STATUS::CLIENT_CONNECTED)
{
/* just for test */
std::string key = std::to_string(tm); LOG_DEBUG("Set key %s", key.c_str());
redisAsyncCommand(m_redis_context, NULL, NULL, "SET %s %s",key.c_str(), "aaa");
redisAsyncCommand(m_redis_context, get_call_fun, (char*)new string(key), "GET %s", key.c_str());
}
else
{
static uint32_t last_tm = ;
if ((tm - last_tm) >= m_timeout_interval)
{
//reconnect
LOG_DEBUG("Start reconnect now ...");
this->connect(); m_timeout_interval = m_timeout_interval * ;
if (m_timeout_interval > )
{
m_timeout_interval = ;
} last_tm = tm;
}
} return ;
} virtual int handle_close(socket_t socket = INVALID_SOCKET, uint32_t mask = )
{
LOG_DEBUG("Enter into handle_close()");
m_client_status = CONNECT_STATUS::CLIENT_UNCONNECTED; // epoll call delete this handler
if (mask & RE_MASK_DEL)
{
LOG_DEBUG("Call RE_MASK_DEL now"); if (this->m_timer_id && (this->reactor() != nullptr))
{
this->reactor()->unregist_timer(this->m_timer_id);
this->m_timer_id = ;
} delete this;
return ;
} this->reactor()->del_event(this,);
return ;
} void clear_redis_context()
{
if (m_delete_redis_context && m_redis_context != nullptr)
{
LOG_DEBUG("Call redisAsynFree() now");
redisAsyncFree(m_redis_context);
m_redis_context = nullptr;
}
} int attach()
{
LOG_DEBUG("Enter attatch function... "); redisContext *context = &(m_redis_context->c);
if (m_redis_context->ev.data != NULL)
{
return -;
} // set callback function
redisAsyncSetConnectCallback(m_redis_context,connectCallBack);
redisAsyncSetDisconnectCallback(m_redis_context,disconnectCallBack); this->set_handle(context->fd); // set handler m_redis_context->ev.addRead = redisReactorAddRead;
m_redis_context->ev.delRead = redisReactorDelRead;
m_redis_context->ev.addWrite = redisReactorAddWrite;
m_redis_context->ev.delWrite = redisReactorDelWrite;
m_redis_context->ev.cleanup = redisReactorCleanup;
m_redis_context->ev.data = this; LOG_DEBUG("ac->ev.data %p", m_redis_context->ev.data); this->add_read();
this->add_write(); return ;
} void add_read()
{
LOG_TRACE_METHOD(__func__); if( (this->m_current_event_mask & reactor::EVENT_READ) > )
{
LOG_DEBUG("EV_READ(0x%0x) already in event_mask 0x%x",
reactor::EVENT_READ, this->m_current_event_mask); return;
} this->reactor()->add_event(this, reactor::EVENT_READ);
} void del_read()
{
LOG_TRACE_METHOD(__func__);
this->reactor()->mod_event(this, this->m_current_event_mask&(~reactor::EVENT_READ));
} void add_write()
{
LOG_TRACE_METHOD(__func__);
this->schedule_write();
} void del_write()
{
LOG_TRACE_METHOD(__func__);
this->cancel_schedule_write();
} void clean_up()
{
LOG_TRACE_METHOD(__func__);
} // note!!!
// connenct not succeed. we can free redis context. ]
// But if connect succeed and borken, we don't connect protected:
std::string m_srv_ip_str;
uint16_t m_srv_port; CONNECT_STATUS m_client_status = CONNECT_STATUS::CLIENT_UNCONNECTED; int m_timer_id = ;
uint32_t m_timeout_value = ;
uint32_t m_timeout_interval = ; bool m_delete_redis_context = true;
redisAsyncContext *m_redis_context = nullptr;
}; static void redisReactorAddRead(void *arg)
{
LOG_DEBUG("Enter redisReactorAddRead() arg %p", arg);
CRedisClient *event_handler = (CRedisClient *)arg;
event_handler->add_read();
} static void redisReactorDelRead(void *arg)
{
CRedisClient *event_handler = (CRedisClient *)arg;
event_handler->del_read();
} static void redisReactorAddWrite(void *arg)
{
CRedisClient *event_handler = (CRedisClient *)arg;
event_handler->add_write();
} static void redisReactorDelWrite(void *arg)
{
CRedisClient *event_handler = (CRedisClient *)arg;
event_handler->del_write();
} static void redisReactorCleanup(void *arg)
{
CRedisClient *event_handler = (CRedisClient *)arg;
event_handler->clean_up();
} void connectCallBack(const redisAsyncContext *ac, int status)
{
if (status != REDIS_OK)
{
LOG_ERROR("connectCallBack() Error: %s", ac->errstr);
return;
} CRedisClient *event_handler = (CRedisClient *)ac->ev.data;
event_handler->open(); LOG_INFO("RedisClient Connected...");
} void disconnectCallBack(const redisAsyncContext *ac, int status)
{
CRedisClient *event_handler = (CRedisClient *)ac->ev.data;
event_handler->handle_close(,); if (status != REDIS_OK)
{
LOG_INFO("disconnectCallBack()!! Error: %s", ac->errstr);
return;
} LOG_INFO("RedisClient Disconnected...");
} #endif /* redis_client_h */

使用的程序样例:

 #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h> //#include <hiredis.h>
//#include <async.h> #include <adapters/redis_client.hpp>
//#include "redis_client.hpp" #include <signal.h> static void signal_handler(int sig)
{
if (sig == SIGINT)
{
reactor::CReactor::instance()->end_event_loop();
}
} /*
void get_call_fun(redisAsyncContext *c, void *r, void *arg)
{
redisReply *reply = (redisReply *)r;
std::string *key_str = (std::string *)arg; if (reply == NULL)
{
delete key_str;
return;
} LOG_INFO("[%s] -> %s\n", key_str->c_str(), reply->str); delete key_str; // Disconnect after receiving the reply to GET
// redisAsyncDisconnect(c);
}
*/ int main (int argc, char **argv)
{
signal(SIGPIPE, SIG_IGN);
signal(SIGINT, signal_handler); CLoggerMgr logger("reactor.prop"); reactor::CReactor *rt = reactor::CReactor::instance();
CRedisClient *redis_client = new CRedisClient("127.0.0.1", , rt);
redis_client->connect(); rt->run_event_loop(); return ;
}

redis async client 与自有框架集成的更多相关文章

  1. Redis java client ==> Jedis

    https://github.com/xetorthio/jedis Jedis is a blazingly small and sane Redis java client. Jedis was ...

  2. Spring集成Redis集群(含spring集成redis代码)

    代码地址如下:http://www.demodashi.com/demo/11458.html 一.准备工作 安装 Redis 集群 安装参考: http://blog.csdn.net/zk6738 ...

  3. Spring cloud 基础框架集成

    Spring cloud 基础框架集成 1. 注册中心 -eurekar 1. pom依赖 <?xml version="1.0" encoding="UTF-8& ...

  4. Spring+SpringMvc+Mybatis框架集成搭建教程

    一.背景 最近有很多同学由于没有过SSM(Spring+SpringMvc+Mybatis , 以下简称SSM)框架的搭建的经历,所以在自己搭建SSM框架集成的时候,出现了这样或者那样的问题,很是苦恼 ...

  5. Spring与其他Web框架集成

    Spring与多种流行Web应用框架(Struts.JSF和DWR)集成的方法. Spring强大的IoC容器和企业支持特性使其十分适于实现Java EE应用的服务和持续层. 对于表现层,可以在许多不 ...

  6. Cordova与现有框架的结合,Cordova插件使用教程,Cordova自定义插件,框架集成Cordova,将Cordova集成到现有框架中

    一.框架集成cordova 将cordova集成到现有框架中 一般cordova工程是通过CMD命令来创建一个工程并添加Android.ios等平台,这样的创建方式可以完整的下载开发过程中所需要的的插 ...

  7. Spring MVC 学习总结(十一)——IDEA+Maven+多模块实现SSM框架集成

    一.SSM概要 与SSH(Struts/Spring/Hibernate/)一样,Spring+SpringMVC+MyBatis也有一个简称SSM,Spring实现业务对象管理,Spring MVC ...

  8. Selenium·自动化框架集成

    date:2018513 day08aft 一.自动化框架集成分层 1.config 配置(项目配置——测试环境,公司环境,线上环境:以中国人才热线登陆为例,网址.用户名.密码等) 2.public ...

  9. Spring MVC 学习总结(十)——Spring+Spring MVC+MyBatis框架集成(IntelliJ IDEA SSM集成)

    与SSH(Struts/Spring/Hibernate/)一样,Spring+SpringMVC+MyBatis也有一个简称SSM,Spring实现业务对象管理,Spring MVC负责请求的转发和 ...

随机推荐

  1. php进程的SIGBUS故障

    某个子站是php写的,访问的时候nginx时不时会冒出现502错误,高峰时更频繁,检查php-fpm的日志发现大量的 child exited on signal 7 (SIGBUS),并且和acce ...

  2. cocos2d-x之文件读写

    bool HelloWorld::init() { if ( !Layer::init() ) { return false; } auto fu=FileUtils::getInstance(); ...

  3. MongodbBackup Script

    #!/usr/bin/env python # _*_coding:utf-8_*_ # Author: "Edward.Liu" # Author-Email: lonnyliu ...

  4. 关于CSS中的字体尺寸设置 em rem等

    常用单位 在CSS中可以用很多不同的方式来设定字体的尺寸.一般来说,这些单位被分成两大类:绝对单位(absolute)和相对单位(relative). 绝对单位在大多数情况下是相对于某些实际量度而言的 ...

  5. Fix "Missing Scripts"

    一.Missing Scripts(脚本引用丢失) 请看下面的两张图的Warn(脚本引用丢失),在某些情况下我们会遇到这个警告. 二.解决办法 参考资料 http://unitygems.com/la ...

  6. 关于JAVA应用中文字体显示小方框的问题解决

    最近碰到linux下jboss应用中中文字体显示为小方框: “在JRE 5以上的java环境中,java会自动加载$JAVA_HOME/jre/lib/fonts目录下的字体.链接或复制宋体或微软雅黑 ...

  7. java 21 - 12 IO流的打印流

    打印流 字节流打印流 PrintStream 字符打印流 PrintWriter打印流的特点: A:只有写数据的,没有读取数据.只能操作目的地,不能操作数据源.(只能写入数据到文件中,而不能从文件中提 ...

  8. jquery给元素添加样式表的方法

    //1.获取和设置样式 $("#tow").attr("class")获取ID为tow的class属性 $("#two").attr(&qu ...

  9. jquery判断div滚动条到底部

    jQuery 里和滚动条有关的概念很多,但是有三个属性和滚动条的拖动有关,就是:scrollTop.scrollLeft.scrollHeight.其中 scrollHeight 属性,互联网上几乎搜 ...

  10. Maven 的 HelloWorld

    <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://mave ...