线程IO模型
阻塞型IO
在调用socket的读写方法时候,在阻塞的情况下,开始写入/读取后,除非结束不然会阻塞线程。
非阻塞型IO
非阻塞IO就是能读多少就读多少,能写多少就写多少,能读多少取决于内核为套接字分配的 读缓冲区
的字节数,能写多少取决于内核为套接字分配的 写缓冲区
的空闲空间字节数。读写完成后,直接返回,线程可以做其他事情,等待下一次读写。
事件轮询(多路复用)
在处理完其他逻辑后,需要重新读写时,调用多路复用API,如 select(read_fds, write_fds, timeout)
,因为select在一定数量描述符时会有严重的性能问题,现在一般使用 epoll(linux)
和 kqueue(FreeBSD/Macosx)
,传入读写描述符,返回读写事件,再通过读写事件进行读写, timeout
参数是用来避免等待事件轮询停顿过长事件,等待超过 timeout
事件就会中断获取事件直接返回。
redis reactor I/O模型
- socket通信:连接redis服务器,服务器创建一个socket进行通信,产生AE_READABLE事件,并将AE_READABLE与连接应答处理器绑定,通过IO多路复用程序进入队列
- 文件事件处理器读取队列读取到AE_READABLE事件之后派发给连接应答处理器,连接答应处理器创建一个新的socket 01与这个客户端进行通信,然后将AE_READABLE事件和命令请求处理器绑定
- 客户端发送请求到服务器,服务器socket 01监听到请求,并发送AE_READABLE事件到IO多路复用程序,将请求加入队列
- 文件事件处理器读取队列读取到AE_READABLE事件之后,派发给命令请求处理器
- 命令请求处理器读取socket 01中的请求,处理请求,准备好给客户端的响应数据之后,将AE_WRITABLE事件绑定到命令回复处理器。当客户端准备好读取响应数据时,就会在socket产生一个AE_WRITABLE事件,事件进入队列中,文件事件分派器读取到后,分派给命令回复处理器,命令回复处理器将准备好的响应数据写入socket,让客户端来读取。
- 命令回复处理器写完之后,就会删除这个socket的AE_WRITABLE事件和命令回复处理器的关联关系。