时间事件保存在aeEventLoop->timeEventHead 以链表的方式进行存储
/* Time event structure */
typedef struct aeTimeEvent {
long long id; /* time event identifier. */
long when_sec; /* seconds */
long when_ms; /* milliseconds */
aeTimeProc *timeProc; //时间事件处理函数
aeEventFinalizerProc *finalizerProc;
void *clientData;
struct aeTimeEvent *next;
} aeTimeEvent;
时间事件API
添加时间事件
long long aeCreateTimeEvent(aeEventLoop *eventLoop, long long milliseconds,
aeTimeProc *proc, void *clientData,
aeEventFinalizerProc *finalizerProc)
{
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; //insert 链表
eventLoop->timeEventHead = te;
return id;
}
删除时间事件(by 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;
//删除时候,执行的finalizerProc回调
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;
}
//时间事件处理函数
static int processTimeEvents(aeEventLoop *eventLoop) {
int processed = 0;
aeTimeEvent *te;
long long maxId;
time_t now = time(NULL);
/* 如果时钟被往回调整,定时jobs强制执行一遍 */
if (now < eventLoop->lastTime) {
te = eventLoop->timeEventHead;
while(te) {
te->when_sec = 0;
te = te->next;
}
}
eventLoop->lastTime = now;
te = eventLoop->timeEventHead;
maxId = eventLoop->timeEventNextId-1;
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;
/*回调定时任务函数,比如serverCron*/
retval = te->timeProc(eventLoop, id, te->clientData);
processed++;
/*重置或者删除*/
if (retval != AE_NOMORE) {
aeAddMillisecondsToNow(retval,&te->when_sec,&te->when_ms);
} else {
aeDeleteTimeEvent(eventLoop, id);
}
te = eventLoop->timeEventHead;
} else {
te = te->next;
}
}
return processed;
}
serverCron
持续运行的redis需要定期对自身资源和状态进行检查和调整,serverCron就是做这件事的。
主要工作:
1 更新服务器各类统计,比如时间、内存占用、数据库占用等情况
2 清理数据库中过期的键值对
3 关闭和清理连接失效的客户端
4 尝试进行aof或rdb持久化操作
5 如果服务器是主服务器,那么对从服务器进行定期同步
添加:
initServer -> aeCreateTimeEvent
if(aeCreateTimeEvent(server.el, 1, serverCron, NULL, NULL) == AE_ERR) {
redisPanic("Can't create the serverCron time event.");
exit(1);
}
执行:
1 watch_dog机制,是为了检测系统超时调用。相应的配置watchdog_period,如果为非0,那么就是执行一遍网络事件耗时超过给定值,那么setitimer 就会释放sigalarm信号, 生成coredump,可以看当前耗时堆栈。
源码:
if (server.watchdog_period) watchdogScheduleSignal(server.watchdog_period);
void watchdogScheduleSignal(int period) {
struct itimerval it;
/* Will stop the timer if period is 0. */
it.it_value.tv_sec = period/1000;
it.it_value.tv_usec = (period%1000)*1000;
/* Don't automatically restart. */
it.it_interval.tv_sec = 0;
it.it_interval.tv_usec = 0;
setitimer(ITIMER_REAL, &it, NULL);
}
2 更新系统cache时间
updateCachedTime()
3 统计,采用循环数组方式,idx指向当前最新方式。
//平均命令数
trackInstantaneousMetric(REDIS_METRIC_COMMAND,server.stat_numcommands);
//平均网络input
trackInstantaneousMetric(REDIS_METRIC_NET_INPUT,server.stat_net_input_bytes);
//平均网络output
trackInstantaneousMetric(REDIS_METRIC_NET_OUTPUT,server.stat_net_output_bytes);
4 更新redis idle 时间
server.lruclock = getLRUClock();
5 记录最大使用内存
if (zmalloc_used_memory() > server.stat_peak_memory)
server.stat_peak_memory = zmalloc_used_memory();
6 客户端管理clientsCron
①处理超时客户端 ② 客户端缓冲区大小调整
7databasesCron 数据库管理