Redis服务启动、事件循环与客户端命令的执行

Redis 服务启动

直接看代码。新的版本中服务器启动代码在 server.c

int main(int argc, char **argv) {
    struct timeval tv;
    int j;

    // 省略 ...

    initServerConfig();
    moduleInitModulesSystem();

    if (argc >= 2) {
    	
    	// ...

        resetServerSaveParams();
        loadServerConfig(configfile,options);// 根据指定的配置文件,初始化服务器配置
        sdsfree(options);
    }

    initServer();// 初始化服务器数据结构,创建aeEventLoop,并注册端口监听

    if (!server.sentinel_mode) {
    	// ...
        
        moduleLoadFromQueue();
        InitServerLast();
        loadDataFromDisk();
        
        // ...
    } else {
        InitServerLast();
        sentinelIsRunning();
    }

    // ...

    aeSetBeforeSleepProc(server.el,beforeSleep); // 钩子函数:每个event执行的前置函数
    aeSetAfterSleepProc(server.el,afterSleep); // 钩子函数:在每个event执行完成后,执行
    
    aeMain(server.el); // 事件循环处理
    
    aeDeleteEventLoop(server.el); // 退出前清理事件

    serverLog(LL_NOTICE, "Self add done");
    return 0;
}

总的来说,服务器启动主要流程如下:

简单来说就是:

1.初始化服务器

2.初始化数据库、构建事件循环、监听端口

3.如果需要,从AOF/RDB中恢复数据

4.事件循环,等待客户端的请求

 

事件循环

Redis 处理的客户端请求、自己的时间周期函数,都是基于事件循环的。

首先在服务器启动时,就创建了 aeEventLoop ,函数如下。该在上边的 initServer 函数内部被调用

// 说明:0、1、2分别表示标准输入、标准输出、标准错误输出
aeEventLoop *aeCreateEventLoop(int setsize) {// 最大文件描述符,默认为 10000+128
    aeEventLoop *eventLoop;
    int i;

    if ((eventLoop = zmalloc(sizeof(*eventLoop))) == NULL) goto err;
    eventLoop->events = zmalloc(sizeof(aeFileEvent)*setsize);
    eventLoop->fired = zmalloc(sizeof(aeFiredEvent)*setsize);
    if (eventLoop->events == NULL || eventLoop->fired == NULL) goto err;
    eventLoop->setsize = setsize;
    eventLoop->lastTime = time(NULL);
    eventLoop->timeEventHead = NULL;
    eventLoop->timeEventNextId = 0;
    eventLoop->stop = 0;
    eventLoop->maxfd = -1;
    eventLoop->beforesleep = NULL;
    eventLoop->aftersleep = NULL;
    if (aeApiCreate(eventLoop) == -1) goto err;
    /* Events with mask == AE_NONE are not set. So let's initialize the
     * vector with it. */
    for (i = 0; i < setsize; i++) // fd就是这个数组的下标
        eventLoop->events[i].mask = AE_NONE;// 表示暂时 未注册事件
    return eventLoop;

err:
    if (eventLoop) {
        zfree(eventLoop->events);
        zfree(eventLoop->fired);
        zfree(eventLoop);
    }
    return NULL;
}

创建后的 aeEventLoop 结构在 redisServer 下,数据结构如下:

aeEventLoop 里面有两类事件:

aeFileEvent:文件事件,简单分为:

AE_READABLE :即可读事件
AE_WRITABLE :可写事件
AE_BARRIER :逆转事件处理顺序(对于同一个fd的事件可读可写时,注意还是一个事件,先处理读再处理写,避免clientData被覆盖丢失)

aeTimeEvent:时间事件

最后 aeFiredEvent 用于存储触发的待处理文件事件。

注意:上边 main 函数的最后,先设置钩子函数,再在 aeMain 中循环处理事件。接下来看下这个事件循环处理 aeMain 函数

void aeMain(aeEventLoop *eventLoop) {
    eventLoop->stop = 0;
    while (!eventLoop->stop) {
        if (eventLoop->beforesleep != NULL) 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值