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. 第一章 Spring Security是什么?

    1. 介绍 1.1 Spring Security是什么? Spring Security是一个强大的和高度可定制的身份验证和访问控制框架. 它是保证基于spring的应用程序安全的实际标准. 1.2 ...

  2. redis状态查看

      https://redis.readthedocs.org/en/latest/server/slowlog.html   https://redis.readthedocs.org/en/lat ...

  3. Java dynamical proxy demo

    今天练习了一下动态代理的一个方面,假设使用它来完成自动设置默认不提交,启动事务,获取到异常则回滚,正常执行则提交. 如果不使用动态代理,则需要在每个方法本身里面设置Connection,写try,ca ...

  4. Hadoop 分布式文件系统 - HDFS

    当数据集超过一个单独的物理计算机的存储能力时,便有必要将它分不到多个独立的计算机上.管理着跨计算机网络存储的文件系统称为分布式文件系统.Hadoop 的分布式文件系统称为 HDFS,它 是为 以流式数 ...

  5. [转]Ionic最佳实践-使用模态窗口modal

    本文转自:http://m.blog.csdn.net/blog/betreex/45649689 原文地址:Ionic最佳实践-使用模态窗口modal 模态窗口的结构 在Ionic中,模态窗口通过$ ...

  6. JVM相关问答

    大部分内容来源网络,整理一下,留个底. 问:堆和栈有什么区别? 答:堆是存放对象的,但是对象内的临时变量是存在栈内存中,如例子中的methodVar是在运行期存放到栈中的. 栈是跟随线程的,有线程就有 ...

  7. leetcode_438_Find All Anagrams in a String_哈希表_java实现

    题目: Given a string s and a non-empty string p, find all the start indices of p's anagrams in s. Stri ...

  8. Genesis 2.8-2.12

    And the LORD God planted a garden eastward in Eden; and there he put the man whom he had formed. 9 A ...

  9. hdu 5800 To My Girlfriend + dp

    传送门:hdu 5800 To My Girlfriend 题意:给定n个物品,其中i,j必选,l,m必不选,问组成体积为s的方法一共有多少种 思路:定义dp[i][j][s1][s2],表示前i种物 ...

  10. string 类的实现

    . #include<iostream> . #include<iomanip> . using namespace std; . . class String{ . frie ...