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. 一个C#的与web服务器交互的HttpClient类

    using System; using System.Collections.Generic; using System.IO; using System.Text; using System.Net ...

  2. CentOS-6.5-saltstack-安装

    官方网站:https://www.saltstack.com/ 官方文档   https://docs.saltstack.cn/contents.html GitHub:  https://gith ...

  3. Redis学习笔记一:数据结构与对象

    1. String(SDS) Redis使用自定义的一种字符串结构SDS来作为字符串的表示. 127.0.0.1:6379> set name liushijie OK 在如上操作中,name( ...

  4. 如何根据屏幕大小改变class的css样式

    /*当屏幕小于1200px*/ @media (max-width:1200px) { ...} 此处针对所有小于1200px屏幕的css属性. /*当屏幕小于1200px且大于992px*/ @me ...

  5. BZOJ1798——[Ahoi2009]Seq维护序列seq

    1.题目大意:区间修改乘法操作和加法操作,求区间和 2.分析:为了填补bzoj2631的坑还是写一发题解吧,首先呢,既然想要双标记,但是这两个标记之间又有着制约作用,所以要定义优先级,这个优先级就定义 ...

  6. BZOJ 1024: [SCOI2009]生日快乐

    Description 将一个 \(x\times y\) 的矩形分成 \(n\) 块,让最长边:最短边 最小. Sol 搜索. \(n\) 只有 \(10\) 写一个类似于记搜的东西就好了. Cod ...

  7. BZOJ 3665: maths

    Sol 矩阵乘法+快速幂+欧拉定理. 首先观察题目可以发现 \(A_n\) 可以表示成关于 \(K\) 和 \(A_0\) 的几次幂的形式. \(A_0\) 就比较简单了 \(m^n\) 所以第一部分 ...

  8. PHP获取IP地址

    获取客户端IP地址:: function getIp(){ if(!empty($_SERVER['HTTP_CLIENT_IP'])){ return $_SERVER['HTTP_CLIENT_I ...

  9. django xadmin多个model的数据渲染在统一个template中

    adminx.py demo class ModelAdmin(object): #.... def get_context(self): context = super(SimCardService ...

  10. mac os x安装php7.0和phalcon3.0

    1,安装xampp(with php7.0) 下载地址: https://www.apachefriends.org/download.html 2,安装phalcon3.0 cd ~/git clo ...