文章目录
Redis的IO多路复用
文件事件处理器
Redis开发了一个文件事件处理器,文件事件处理器使用I/O多路复用(multiplexing)程序来同时监听多个套接字, 并根据套接字目前执行的任务来为套接字关联不同的事件处理器。
当被监听的套接字准备好执行 连接应答(accept)、读取(read)、写入(write)、关闭(close)等操作时, 与操作相对应的文件事件就会产生,此时,文件事件处理器就会调用套接字之前关联好的事件处理器来处理这些事件。
虽然文件事件处理器以单线程方式运行, 但通过使用I/O多路复用程序来监听多个套接字, 又可以很好地与Redis服务器中其以单线程方式运行的模块进行对接, 这保持了 Redis内部单线程设计的简单性。
文件事件处理器的四个组成部分:
- 套接字
- I/O多路复用程序
- 文件事件分派器(dispatcher)
- 事件处理器
- 文件事件是对套接字操作的抽象,每当一个套接字准备好 连接应答(accept)、写入、 读取、 关闭等操作时,就会产生一个文件事件。
- 注意,因为一个服务器通常会连接多个套接字, 所以多个文件事件有可能会并发地出现。
- 其中,【I/O多路复用程序】负责监听多个套接字,并向【文件事件分派器】传送那些产生了事件的套接字。
- 当文件事件产生时,会被顺序的加载到一个队列里面, 然后通过这个队列一个一个地向【文件事件分派器】传送套接字,当上一个套接字产生的事件被处理完毕之后,【I/O多路复用程序】才会继续向文件事件分派器传送下一个套接字。
- 文件事件分派器接收I/O多路复用程序传来的套接字, 并根据套接字产生的事件的类型, 调用相应的事件处理器。
【I/O多路复用程序】的实现
Redis的I/O多路复用程序的所有功能都是通过包装常见的select、epoll、evport、kqueue这些I/O多路复用函数库来实现的。
利用select、poll、epoll可以同时监察多个流的IO事件的能力,在空闲的时候会把当前线程阻塞,当有一个或多个流由IO事件发生时,就从阻塞态中唤醒,于是程序就会轮询一遍所有的流(epoll只是轮询那些真正发出了时间的流),并且一次顺序的处理就绪的流。
- select:服务端一直在轮询、监听如果有客户端链接上来就创建一个连接放到数组A中,继续轮询这个数组,如果在轮询的过程中有客户端发生IO事件就去处理;select只能监视1024个连接(一个进程只能创建1024个文件);而且存在线程安全问题;
- poll:在select做了许多修复,比如不限制监测的连接数;但是也有线程安全问题;
- epoll:也是监测IO事件,但是如果发生Io事件,它会告诉你是哪个连接发生了事件,就不用再轮询访问。而且它是线程安全的,但是只有linux平台支持;
文件事件的处理器
Redis为文件事件编写了多个处理器, 这些事件处理器分别用于实现不同的网络通信需求, 比如说:
- 为了对连接服务器的各个客户端进行应答, 服务器要为监听套接字关联【连接应答处理器】。
- 为了接收客户端传来的命令请求, 服务器要为客户端套接字关联【命令请求处理器】。
- 为了向客户端返回命令的执行结果, 服务器要为客户端套接字关联命令【回复处理器】。
- 当主服务器