Redis的定时器是自己实现的,不是很复杂。说说具体的实现吧。

定时器的存储维护采用的是普通的单向链表结构,具体节点定义为:

 /*时间定时器结构体*/
typedef struct aeTimeEvent
{
long long id; /*定时器的编号*/
long when_sec; /* seconds */
long when_ms; /* milliseconds */
aeTimeProc *timeProc;/*时间到达处理函数*/
aeEventFinalizerProc *finalizerProc;/*删除清理函数*/
void *clientData;/*带外数据*/
struct aeTimeEvent *next;/*定时器的存储采用的是链表结构*/
} aeTimeEvent;

定时器记录的根节点的位置是在事件管理器中,剩下的就是普通的操作函数了

 /*添加定时器事件,参数为时间控制器,定时时间,处理函数,函数参数,清理函数*/
long long aeCreateTimeEvent(aeEventLoop *eventLoop, long long milliseconds,
aeTimeProc *proc, void *clientData,
aeEventFinalizerProc *finalizerProc)
{
/*生成ID*/
long long id = eventLoop->timeEventNextId++;
aeTimeEvent *te; te = zmalloc(sizeof(*te));
if (te == NULL) return AE_ERR;
te->id = id;
/*调整时间*/
aeAddMillisecondsToNow(milliseconds,&te->when_sec,&te->when_ms);
te->timeProc = proc;
te->finalizerProc = finalizerProc;
te->clientData = clientData;
/*加入时间链表中,所有的时间节点都是在头部插入的,没顺序*/
te->next = eventLoop->timeEventHead;
eventLoop->timeEventHead = te;
return id;
}
 /*删除时间节点,提供时间点的ID就好,如果没找到就返回错误*/
int aeDeleteTimeEvent(aeEventLoop *eventLoop, long long id)
{
aeTimeEvent *te, *prev = NULL; te = eventLoop->timeEventHead;
/*循环查找节点,调用清理函数并释放内存*/
while(te)
{
if (te->id == id)
{
if (prev == NULL)
eventLoop->timeEventHead = te->next;
else
prev->next = te->next;
if (te->finalizerProc)
te->finalizerProc(eventLoop, te->clientData);
zfree(te);
return AE_OK;
}
prev = te;
te = te->next;
}
return AE_ERR; /* NO event with the specified ID found */
}
 /*查找激活时间最短的节点*/
static aeTimeEvent *aeSearchNearestTimer(aeEventLoop *eventLoop)
{
aeTimeEvent *te = eventLoop->timeEventHead;
aeTimeEvent *nearest = NULL; while(te)
{
if (!nearest || te->when_sec < nearest->when_sec || (te->when_sec == nearest->when_sec && te->when_ms < nearest->when_ms))
nearest = te;
te = te->next;
}
return nearest;
}
 /* Process time events 处理时间事件,先执行定时器事件,如果有时间设置过端的情况,会导致整个卡死*/
static int processTimeEvents(aeEventLoop *eventLoop)
{
int processed = ;
aeTimeEvent *te;
long long maxId;
time_t now = time(NULL); if (now < eventLoop->lastTime) /*为啥会出现当前时间小于上次激活时间的问题,重新设置了系统时间,当前时间小于了最后的插入时间*/
{
te = eventLoop->timeEventHead;
while(te)
{
te->when_sec = ;
te = te->next;
}
}
eventLoop->lastTime = now;/*更新最后操作时间*/ te = eventLoop->timeEventHead;
maxId = eventLoop->timeEventNextId-;
/*时间处理,从链表中逐个检查,找到到达时间的定时器后调用处理函数,然后重新从头遍历,当某个定时器的*/
while(te)
{
long now_sec, now_ms;
long long id; if (te->id > maxId)
{
te = te->next;
continue;
}
aeGetTime(&now_sec, &now_ms);
if (now_sec > te->when_sec || (now_sec == te->when_sec && now_ms >= te->when_ms))
{/*当该节点时间到达时,调用时间处理函数,根据函数的返回来决定是否需要删除定时节点*/
int retval; id = te->id;
retval = te->timeProc(eventLoop, id, te->clientData);
processed++; /*根据函数的返回值来确定是否仍需注册,返回值为下次的激活时间*/
if (retval != AE_NOMORE)
{
/*返回值不为-1时需要重新注册函数,返回值为下次激活的时间*/
aeAddMillisecondsToNow(retval,&te->when_sec,&te->when_ms);
}
else
{
/*删除定时器*/
aeDeleteTimeEvent(eventLoop, id);
}
/*定时器函数处理完毕之后为了防止漏掉节点,重新从头结点遍历,这个地方要注意,如果定时时间太短,这个地方会造成死循环,不停的处理定时器事件*/
te = eventLoop->timeEventHead;
}
else
{
te = te->next;
}
}
return processed;
}

Redis事件管理(二)的更多相关文章

  1. Redis事件管理(一)

    Redis统一的时间管理器,同时管理文件事件和定时器, 这个管理器的定义: #if defined(__APPLE__) #define HAVE_TASKINFO 1 #endif /* Test ...

  2. Redis事件管理(三)

    Redis的事件管理和定时器的管理都是自己来实现的,Redis的事件管理分为两部分,一部分是封装了系统的异步事件API,还有一部分是在这基础上封装了一个通用的事件管理器,根据具体的系统来决定具体使用哪 ...

  3. zendframework 事件管理(二)

    首先需要明确的几个问题: Q1.什么是事件? A:事件就是一个有名字的行为.当这个行为发生的时候,称这个事件被触发. Q2.监听器又是什么? A:监听器决定了事件的逻辑表达,由事件触发.监听器和事件往 ...

  4. redis的管理工具

    phpredisadmin工具 rdbtools管理工具 saltstack管理redis 通过codis完成redis管理 一:phpredisadmin工具:类似于mysqladmin管理mysq ...

  5. Redis事件

    Redis事件 Redis的ae(Redis用的事件模型库) ae.c Redis服务器是一个事件驱动程序,服务器需要处理以下两类事件: 文件事件(file event):Redis服务器通过套接字与 ...

  6. 服务器文档下载zip格式 SQL Server SQL分页查询 C#过滤html标签 EF 延时加载与死锁 在JS方法中返回多个值的三种方法(转载) IEnumerable,ICollection,IList接口问题 不吹不擂,你想要的Python面试都在这里了【315+道题】 基于mvc三层架构和ajax技术实现最简单的文件上传 事件管理

    服务器文档下载zip格式   刚好这次项目中遇到了这个东西,就来弄一下,挺简单的,但是前台调用的时候弄错了,浪费了大半天的时间,本人也是菜鸟一枚.开始吧.(MVC的) @using Rattan.Co ...

  7. jquery技巧之让任何组件都支持类似DOM的事件管理

    本文介绍一个jquery的小技巧,能让任意组件对象都能支持类似DOM的事件管理,也就是说除了派发事件,添加或删除事件监听器,还能支持事件冒泡,阻止事件默认行为等等.在jquery的帮助下,使用这个方法 ...

  8. Redis 内存管理与事件处理

    1 Redis内存管理 Redis内存管理相关文件为zmalloc.c/zmalloc.h,其只是对C中内存管理函数做了简单的封装,屏蔽了底层平台的差异,并增加了内存使用情况统计的功能. void * ...

  9. 安装window下的redis,redis可视化管理工具(Redis Desktop Manager)安装,基础使用,实例化项目

    以下包括内容: 一.redis下载安装,启动 二.Redis可视化管理工具(Redis Desktop Manager)安装 三.实例化项目 一.redis下载安装,启动 1,redis官方下载地址: ...

随机推荐

  1. 巧用jQuery选择器写表单办法总结(提高效率)

    转载自:http://blog.csdn.net/violetjack0808/article/details/52221343 1.文本和文本框 <!DOCTYPE html> < ...

  2. MFC关闭子窗口 如何把父窗口也一起关闭

    在子窗口OnClose() 消息里添加: GetParent()->DestroyWindow();//子窗口关闭 父窗口也同样关闭

  3. VM虚拟机下安装Centos7.0图文教程

    新建虚拟机的相关配置,LZ使用的是VMware workstation 10.2 ,(其它版本也ok的),配置见下图.. PS: 打开虚拟机之后,提示了一个小错误,LZ根据错误提示,到BIOS里面设置 ...

  4. JavaScript与DOM

    文档对象模型Document Object Model DOM(Document Object Model,文档对象模型)是一个通过和JavaScript进行内容交互的API.Javascript和D ...

  5. zabbix 3.0.4 监控windows 服务

    下载客户端 http://www.zabbix.com/download.php http://www.zabbix.com/downloads/3.0.4/zabbix_agents_3.0.4.w ...

  6. 分布式系统一致性算法 raft学习

    在学习MongoDB的过程中,有博客中写道其搭建复制集时使用了raft算法,经过简单地的搜索资料后,发现了一个特别好的网站资料.这个网站用动画的形式,非常清楚和详尽的解释了整个raft算法的精要和过程 ...

  7. PHP中为位运算符(几乎很少用)

    PHP语言里的位运算符&.|.^ .~.〈〈 .〉〉 "&" 按位与运算 按位与运算符"&"是双目运算符.其功能是参与运算的两数各对应的 ...

  8. 如何安装PANABIT?

    PANABIT可以帮你轻松的封杀360WIFI.二级路由和移动设备,还可以让员工在上班期间禁止浏览与工作无关的网站,禁止看视频,禁止聊QQ,禁止网购......总之一切你能想到的,它都能帮你实现. P ...

  9. 获取客户端IP

    function getIP(){ $ip = ""; if (getenv("HTTP_CLIENT_IP") && strcasecmp(g ...

  10. 解决IDEA自动重置LanguageLevel和JavaCompiler版本的问题

    使用IDEA时,导入的Maven项目默认的LanguageLevel和JavaCompiler都是1.5,1.5的情况下连最简单的@Override注解都不支持,所以项目可能出现一堆错. 虽然在项目上 ...