Redis线程模型
1.文件事件处理器
File Event Handler,文件事件处理器是Redis基于reactor模式开发的网络事件处理器。
文件处理器由4部分组成,分别是多个套接字,IO多路复用程序,文件事件分派器,事件处理器。由于文件事件分派器队列的消费是单线程的,所以Redis被叫做单线程模型。
2.消息处理流程
文件事件处理器使用I/O多路复用程序来同时监听多个套接字,并根据这个套接字所执行的任务来为套接字关联不同的事件处理器。
当被监听的套接字准备好执行应答、读取、写入、关闭等操作时,与操作相应的文件事件就会产生,这时文件事件处理器就会调用套接字之前关联好的事件处理器来处理这些事件。
尽管多个文件事件可能会并发的产生,但I/O多路复用将所有产生事件的套接字都推到了一个队列中,然后通过这个队列有序的,同步的,以每次一个套接字的方式向文件事件分派器传送套接字;当上一个套接字产生的事件被处理完毕之后,I/O多路复用程序才会继续向文件事件分派器传送下一个套接字。
3.I/O多路复用程序的实现
Redis的I/O多路复用程序所有功能是通过包装select、epoll、evport和kqueue这些I/O多路复用函数库来实现的,每个I/O多路复用函数库在Redis源码中都对应一个单独的文件,比如ae_select.c、ae_epoll.c、ae_kqueue.c等。
Redis为每个I/O多路复用函数库都实现了相同的API,并在I/O多路复用程序的实现源码中用定义了相应的规则,从而使得程序会在编译时自动选择系统中性能最好的I/O多路复用函数库,来作为Redis的I/O多路复用程序的底层实现。
4.文件事件类型
- 当套接字变得可读时,也就是客户端对套接字执行write操作,或者执行close操作时,套接字会产生AE_READABLE 事件。
- 当套接字变得可写时,也就是客户端对套接字执行read操作,套接字产生AE_WRITABLE事件。
I/O多路复用程序允许服务器同时监听套接字的AE_READABLE事件和AE_WRITABLE事件,如果一个套接字同时产生了这两种事件,那么文件事件分派器会优先处理AE_READABLE事件,等到AE_READABLE事件处理完之后,才处理AE_WRITABLE 事件。这也就是说,如果一个套接字又可读又可写的话,那么服务器将先读套接字,后写套接字。
事件处理器
Redis为文件事件编写了多个处理器,这些事件处理器分别用于实现不同的网络通讯需求,常用的处理器如下:
连接应答处理器:对连接服务器的客户端进行应答。
- 当有客户端连接服务器监听套接字的时候, 套接字就会产生AE_READABLE 事件, 从而引发连接应答处理器执行。
命令请求处理器:接收客户端传来的命令请求。
- 当客户端向服务器发送命令请求的时候,套接字就会产生 AE_READABLE事件,引发命令请求处理器执行。
- 在客户端连接服务器的整个过程中,服务器都会一直为客户端套接字的AE_READABLE事件关联命令请求处理器。
命令回复处理器:向客户端返回命令的执行结果。
- 当客户端准备好接收服务器传回的命令回复时,就会产生AE_WRITABLE事件,引发命令回复处理器执行。
- 当命令回复发送完毕之后, 服务器就会解除命令回复处理器与客户端套接字的 AE_WRITABLE 事件之间的关联。
一次完整的客户端与服务器连接事件示例
假设Redis服务器正在运作,那么这个服务器的监听套接字的AE_READABLE事件应该正处于监听状态之下,而该事件所对应的处理器是连接应答处理器。
如果这时有一个Redis客户端向Redis服务器发起连接,那么监听套接字将产生AE_READABLE事件, 触发连接应答处理器执行:处理器会对客户端的连接请求进行应答, 然后创建客户端套接字,以及客户端状态,并将客户端套接字的 AE_READABLE 事件与命令请求处理器进行关联,使得客户端可以向主服务器发送命令请求。
之后,客户端向Redis服务器发送一个命令请求,那么客户端套接字将产生 AE_READABLE事件,引发命令请求处理器执行,处理器读取客户端的请求内容, 然后传给相关程序去执行。
执行命令会产生相应的命令回复,为了将这些命令回复传送回客户端,服务器会将客户端套接字的AE_WRITABLE事件与命令回复处理器进行关联:当客户端尝试读取命令回复的时候,客户端套接字将产生AE_WRITABLE事件, 触发命令回复处理器执行, 当命令回复处理器将命令回复全部写入到套接字之后, 服务器就会解除客户端套接字的AE_WRITABLE事件与命令回复处理器之间的关联。