redis 时间事件

时间事件保存在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 数据库管理

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值