Redis服务器是一个事件驱动程序,服务器需要处理两类事件:文件事件(file event)和时间事件(time event)
Redis事件处理流程
aeMain
函数通过调用aeProcessEvents
函数来进行文件事件和时间事件的调度和执行。aeEventLoop
中记录了事件相关的信息。首先通过aeSearchNearestTimer
函数获取最短的时间事件的执行时间间隔n
,然后调用aeApiPoll
函数获取监听到的套接字,最后执行与套接字向对应的事件处理函数rfileProc
和wfileProc
,最后再执行时间事件函数processTimeEvents
文件事件
Redis的基于Reactor模式开发了自己的网络事件处理器,这个处理器被称为文件事件处理器(file event handler):
- 文件事件处理器使用IO多路复用程序来监听多个套接字,并根据套接字目前执行的任务为套接字关联不同的事件处理器
- 当被监听的套接字准备好执行连接应答(accept)、读取(read)、写入(write)、关闭(close)等操作,当文件事件产生时,这些文件事件处理器就会调用套接字之前关联好的事件处理器来处理事件
文件事件处理器的构成
文件事件的处理器
Redis为文件事件编写了多个处理器:
- 连接应答处理器:当Redis服务器进行初始化是,程序会将这个连接应答处理器和服务监听套件字的
AE_READABLE
事件关联起来,当有客户端用connect
函数连接服务器监听套接字是,套接字就会产生AE_READABLE
事件,引发连接应答处理器执行,并执行相应的套接字应答操作 - 命令请求处理器:当一个客户端通过连接应答处理器成功连接到服务器之后,服务器会将客户端套接字的
AE_READABLE
事件和命令请求处理器关联起来,当客户端向服务器发送命令请求时,套接字就会产生AE_READABLE
事件,引发命令请求处理器执行,并执行相应的套接字读入操作 - 命令回复处理器:当服务器有命令回复需要传递给客户端时,服务端会将客户端套接字的
AE_WRITABLE
事件和命令回复处理器关联起来,当客户端准备好接收服务器传回的命令回复时,就会产生AE_WRITABLE
事件,引发命令回复处理器执行,并执行相应的套接字写入操作
一次完整的客户端与服务端连接事件
- 服务器监听套件字的
AE_READABLE
事件,当客户端发送连接请求产生AE_READABLE
事件,服务端会对客户端的连接请求进行应答,将客户端套接字的AE_READABLE
事件与命令请求处理器关联,客户端可以向服务端发送命令请求了 - 客户端向服务端发送一个命令请求,客户端套接字将产生
AE_READABLE
事件,引发命令处理器去执行,执行命令将产生相应的命令回复,服务端将客户端套接字的AE_WRITABLE
事件与命令回复处理器关联 - 客户端尝试读取命令回复时,客户端套接字将产生
AE_WRITABLE
事件,触发命令回复处理器执行,当命令回复处理器将命令回复全部写入套接字之后,服务器就会接触客户端套接字的AE_WRITABLE
事件与命令回复处理器之间的关联
时间事件
Redis的时间事件分为定时事件和周期性事件。一个时间事件由三个属性组成:
id
:服务器为时间时间创建的全局唯一IDwhen
:记录了时间时间的到达时间(毫秒精度的UNIX时间戳)timeProc
:时间事件处理器
服务器所有的时间事件都放在一个无序链表中,每当时间事件执行器运行时,它就遍历整个链表,查找所有已到达的时间事件,并调用相应的事件处理器。正常模式下的Redis服务器只使用serverCron
一个时间事件,而在benchmark模式下,服务器也只使用两个时间事件,所以不影响事件执行的性能