事件
Redis 基于 Reactor 模式开发了自己的网络时间处理器:文件事件处理器(File Event Handler)
- 文件事件处理器基于 I/O 多路复用(multiplexing)程序来同时监听多个套接字(Socket),并根据套接字目前执行的任务来为套接字关联不同的事件处理器。
- 当被监听的套接字准备好执行连接应答(accept)、读取(read)、写入(write)、关闭(close)等操作时,与操作相对应的文件事件就会产生,此时文件事件处理器就会调用套接字之前关联好的事件处理器来处理具体的事件。
虽然文件事件处理器以单线程的方式运行,但是通过 I/O 多路复用(multiplexing)来监听多个套接字,文件事件处理器既实现了高性能的网络通信模型,又可以很好的和 Redis 内部同样以单线程方式运行的模块很好的对接,保持了 Redis 内部单线程设计的简单性。
构成
文件事件处理器包括四个部分:套接字、I/O 多路复用程序、文件事件分派器、事件处理器。
I/O 多路复用
I/O 多路复用程序监听多个套接字,并向文件事件分派器传递那些产生了事件的套接字。
一个服务器连接多个套接字,所以文件事件可能会并发出现,但是 I/O 多路复用程序总是将产生事件的套接字放到一个队列里面,然后通过这个队列,以有序、同步、每次一个套接字的方式向文件事件分派器传送套接字。
Redis 根据操作系统,自动选择最高效率的 I/O 多路复用实现:
/* Include the best multiplexing layer supported by this system.
* The following should be ordered by performances, descending. */
#ifdef HAVE_EVPORT
#include "ae_evport.c"
#else
#ifdef HAVE_EPOLL
#include "ae_epoll.c"
#else
#ifdef HAVE_KQUEUE
#include "ae_kqueue.c"
#else
#include "ae_select.c"
#endif
#endif
#endif
文件事件分派器
文件事件分派器结构 I/O 多路复用程序传来的套接字,并根据套接字产生的事件类型,调用对应的事件处理器。
事件处理器
事件处理器是一个个函数,定义了某个事件发生时,服务器应该执行的动作, 服务器为不同任务的套接字关联不同的事件处理器。
事件的类型
I/O 多路复用程序监听多个套接字的读和写事件:
- 套接字变得可读:客户端对套接字执行 write 操作,或者 close 操作,或者有新的可应答(acceptable)套接字出现时(客户端对服务器的监听套接字执行 connect 操作),此时服务器的套接字会产生 AE_READABLE 事件。
- 套接字变得可写:客户端对服务端的套接字执行 read 操作,服务器的套接字将产生 AE_WRITABLE 事件。
详情见源码文件:
ae_epoll.c、ae.c、networking.c