一.main函数主流程
1)事件循环保存在变量server.el中,initServer中创建了事件循环
typedef struct aeEventLoop {
int maxfd; /* highest file descriptor currently registered */
int setsize; /* max number of file descriptors tracked */
long long timeEventNextId;
time_t lastTime; /* Used to detect system clock skew */
aeFileEvent *events; /* Registered events */
aeFiredEvent *fired; /* Fired events */
aeTimeEvent *timeEventHead;
int stop;
void *apidata; /* This is used for polling API specific data */
aeBeforeSleepProc *beforesleep;
} aeEventLoop;
事件循环成员eventLoop->apidata保存了如下结构
typedef struct aeApiState {
int epfd;
struct epoll_event *events;
} aeApiState;
其中,epfd是io复用描述符,events指针用于存放可读或者可写的事件;
2)initserver中创建定时器
aeCreateTimeEvent(server.el, 1, serverCron, NULL, NULL)
3)添加监听的tcp连接,和unix套接字
aeCreateFileEvent(server.el,server.ipfd[j], AE_READABLE,acceptTcpHandler,NULL)
aeCreateFileEvent(server.el,server.sofd,AE_READABLE,
acceptUnixHandler,NULL)
4)进入主循环aeMain
aeMain中调用aeProcessEvents处理定时器事件和网络事件;
二 .事件来源
1).每秒server.hz一次的周期任务
initServer中,调用aeCreateTimeEvent(server.el, 1, serverCron, NULL, NULL)第一次添加;回调函数是serverCron;
执行如下任务:
- updateCachedTime,更新时间;
- 统计收到的命令个数,收到字节个数,发送的字节个数;
- 更新server.lruclock,用于把长时间不使用的key置换到磁盘;
- clientsCron,客户端定时任务;
- databasesCron,数据库定时任务;
- 执行持久化任务;
- replicationCron 执行主从复制任务;
- clusterCron,执行集群任务,如果是集群模式;
- sentinelTimer,如果卫士模式,执行卫士模式的定时器;
2).接收tcp连接
在initServer中,对每个监听的socket,设置accept回调函数acceptTcpHandler,acceptTcpHandler中接收每个连接,并把描述符添加到监听中,设置可读的回调函数为readQueryFromClient
3).客户端命令
收到客户端命令时,会执行回调函数readQueryFromClient