一 概述
让应用程序可以同时对多个I/O端口进行监控以判断与其有关的操作是否可以进行,从而达到时间复用目的,例如:监控来自10条不同火车路线(I/O端口)是否有列车到达(即是否可读),那么需要10个人(相当于10个线程或10处代码)来完成这项任务。如果利用某种技术(如摄像监控技术)将10条路线的情况监控情况统一传达至某一点(如监控室),那么就只需要一个人(一条线程)在监控室就可监控10条路线的列车情况。类似于select或者epoll这样的多路I/O复用机制就如同摄像头,它们能够将多个I/O端口的状况反馈到同一处,比如某个特定的文件描述符上,这样应用程序只需要利用select()或epoll()系统调用用来阻塞此处即可。
二 文件描述符(File Descriptor)
一个打开的文件通过唯一的描述符进行引用,该描述符是打开文件的元数据到文件本身的映射。
三 传统的阻塞I/O模型
当使用read或者write对一个文件描述符FD进行读写时,如果当前的文件描述符FD是不可读或者不可写的时候,则整个软件服务都不会对请求做出响应,导致整个服务都无法使用,这就是传统意义上的阻塞I/O模型。而且这种阻塞模型会影响其他FD对应的服务,所以在进行多个客户端任务处理的时候,往往不会使用阻塞模型。
四 select及其他系统调用
select系统调用可以检测多个文件描述符FD的可读可写的情况,当系统中存在可读或者可写的文件描述符FD的时候,select函数可以返回可读可写的FD的个数。当监听交给select函数的后,我们的程序可以继续去响应其他请求。
select系统调用方法的时间复杂度为o(n)。
除了select外还有epoll,kqueue,evport等不同的系统调用,Redis会优先选择时间复杂度为O(1)的I/O多路复用函数作为底层实现,而select是所有系统中都会有的系统调用,所以当系统中没有其他多路复用函数的时候,就会使用select系统调用。
五 基于react设计模式的Redis服务
Redis服务是基于react设计模式来实现文件事件处理器,文件事件处理器是利用I/O多路复用模块,通过监听不同的事件发生,文件事件就会回调FD绑定的事件处理器,虽然事件处理器是在单线程上运行的,但是通过I/O多路复用模块的使用,实现了对多个FD引用读写的监控,提高了网络通信模型的性能,从而保证Redis服务使用变得方便。