事件
Redis服务器是一个事件驱动程序,服务器需要处理两种事件: 1. 文件事件 2. 事件事件 本文会主要从这两个方面介绍
文件事件
Redis基于Reactor模式开发了自己的网络事件处理器,即文件事件处理器
具体来说: 文件事件处理器通过IO多路复用程序来监听多个套接字,并且根据套接字目前执行的任务为套接字关联不同的事件处理器,当被监听的套接字准备好执行相应操作时,与操作相对应的文件事件就会产生,此时文件事件处理器就会调用先前绑定在套接字上对应的事件处理器来处理这些事件。
简单来说就是以IO多路复用同时监听多个套接字,以单线程的方式运行事件处理器
从上文的描述我们可以把Redis的文件事件处理器分为四个部分:
- 套接字
- IO多路复用程序
- 事件分派器
- 事件处理器
文件事件是对套接字操作的抽象,每当套接字准备好相应的操作时,对应的文件事件就会产生,显然可以有多个文件事件并发产生
IO多路复用程序,redis服务器会同时监听多个套接字,并且向事件分派器传递哪些产生了事件的套接字
事件分派器,接收IO多路复用程序传递的套接字,这里多个并发产生的事件会以队列的形式逐一执行
事件处理器,处理对应的事件
IO多路复用程序
常见的IO多路复用有SELECT、POLL、EPOLL,redis封装了底层的细节,会自动选取效果最佳的方法
事件的类型
- 可读,当客户端执行write或者connect操作时,套接字会变得可读,产生可读事件
- 可写,当客户端执行read操作时,会产生可写事件
当一个套接字又可读又可写时,服务器先读套接字,后写套接字
方法
- aeCreateFileEvent: 函数接收一个套接字描述符,一个事件类型,以及一个事件处理器作为参数,将给定的套接字的给定事件加入IO多路复用程序的监听范围之内,并且把该事件与事件处理器相连。
- aeDeleteFileEvenet:删除操作
- aeGetFileEvents: 接收一个套接字,返回该套接字正在被监听的事件类型[AE_NONE AEREADABLE AE_WRITABLE AE_READABLE]
- aewait 接收一个套接字描述符、一个事件类型和一个毫秒数为参数,在指定时间内,得到产生的事件或者超时返回
- aeApiPoll: 阻塞等待所有设置为监听状态的套接字产生事件,或者超时返回
- aeProcessEvents: 遍历所有已产生的事件,并调用相应的事件处理器来处理这些事件
- aeGetApiName: 返回IO多路复用底层使用的函数
文件事件处理器
Redis编写了多个事件处理器,分别用来处理客户端连接、命令请求、返回响应、主从复制
- 连接应答处理器
当Redis服务器进行初始化的时候,程序会将这个连接应答处理器和服务器监听套接字的AE_READABLE事件关联起来,当客户端调用connet函数时,就会产生可读事件,从而处理连接 - 命令请求处理器
当客户端通过连接应答处理器成功连接到服务端之后,服务器会将客户端套接字的AE_READABLE事件和命令请求处理器关联起来,当客户端向服务端发送命令请求的时候,套接字就会产生AE_READABLE事件 - 命令回复处理器
当服务器有命令回复需要传送给客户端时,服务器会将客户端套接字的AE_WRITEABLE事件和命令回复处理器关联起来,当客户端准备好接收服务器传回的命令回复时,就会产生AE_WRITEABLE事件,引发命令回复处理器的执行。
总流程:
Redis服务器正在运行,AE_READABLE事件正在处于监听状态之下,而事件所对应的处理器为连接应答处理器,当Redis客户端发起请求时,监听的套接字将会产生可读事件,触发连接应答处理器的执行,创建一个客户端套接字,并将可读事件与命令请求处理器绑定,使得客户端可以向主服务器发送命令请求。当客户端发送了一次命令请求后,引发命令请求处理器执行,并且会将该客户端可写事件与命令回复处理器绑定,执行命令回复操作
时间事件
时间事件分为两种:定时事件、周期事件
一个时间时间主要由以下三个属性组成:
- id:服务器为时间创建的全局唯一ID。ID号按从小到大的顺序递增
- when:UNIX时间戳,记录时间事件的到达时间
- timeProc: 时间事件处理器,当时间事件到达时会调用相应的处理器来处理事件
具体实现
服务器将所有时间事件放在一个无序链表中,每当时间事件执行器运行时,遍历链表找到对应的已到达的时间事件,并调用相应的事件处理器。
这里无序链表并不影响性能,因为通常来说这个链表非常短,近似与指针
方法
这里的方法与文件事件相似,不过多赘述
servercron函数
- 更新服务器中各类统计信息
- 清理数据库中的过期键值对
- 关闭和清理连接失效的客户端
- 尝试进行AOF或RDB持久化
- 如果服务器是主服务器,那么对从服务器进行定期同步
- 如果处于集群状态,对集群进行定期同步和连接调试
文件事件和时间事件的调度问题
简单来说,由于时间事件是定时的、周期性的,文件事件是随机出现的,因此整个事件的处理过程就是等待时间事件到达,期间处理产生的文件事件