注:本文只是我浅显的理解了一下IO多路复用,用于应对面试,如果有错误,请在评论区指正,谢谢
面试官:
说说你对IO多路复用的理解?
我:
IO多路复用是一种高效地管理多个文件描述符(FD)的方式,它允许同时监听多个IO事件并在有事件发生时立即响应。
在传统的IO编程中,每个socket连接都需要一个线程或进程来处理,这样就会导致系统资源的浪费和性能问题。而IO多路复用则可以通过一个线程或进程来同时管理多个socket连接,并且可以同时处理多个连接上的IO事件。
常用的IO多路复用技术有select、poll、epoll等。
以select为例,当一个进程调用select函数时,它会将多个文件描述符注册到一个监控集合中,并设置监听事件类型(如可读、可写、异常等)。然后,select函数会阻塞进程,直到监控集合中的任意一个文件描述符发生了监听事件(读、写)。此时,select函数就会返回,并告诉进程哪些文件描述符有事件发生,进程可以根据返回值来处理相应的IO事件。
相比于传统的IO编程方式,IO多路复用的优势在于:
- 节省系统资源。使用IO多路复用可以通过一个线程或进程来管理多个socket连接,而不需要为每个连接都创建一个线程或进程,从而避免了过多的系统资源占用。
- 提高程序性能。在传统的IO编程方式中,每个连接都需要独立地进行IO操作,而IO多路复用可以同时(这里要求是多线程模型才可以同时,也就是并行,如果是单线程模型那么其实是并发)处理多个连接上的IO事件(因为他为每一个不同的事件类型都绑定了对应的处理器,这些处理器可以帮助对应的连接处理事件),从而减少了线程或进程的切换开销,提高了程序的性能。
- 便于管理IO事件。使用IO多路复用可以将多个文件描述符注册到一个监控集合中,并设置监听事件类型,这样可以方便地管理多个IO事件,提高程序的可维护性。
需要注意的是,IO多路复用技术虽然可以提高程序的性能和可维护性,但它也需要谨慎使用,特别是在高并发和大规模的网络应用中。因为过多的文件描述符注册和IO事件处理会导致系统资源的浪费和性能下降,而且对于不同的操作系统和网络环境,不同的IO多路复用技术的性能表现也有所不同,需要根据具体情况进行选择。
例如,Redis 通过 IO 多路复用程序 来监听来自客户端的大量连接(或者说是监听多个 socket),它会将感兴趣的事件及类型(读、写)注册到内核中并监听每个事件是否发生。这样的好处非常明显: I/O 多路复用技术的使用让 Redis 不需要额外创建多余的线程来监听客户端的大量连接,降低了资源的消耗(和 NIO 中的 Selector 组件很像),Redis6.0之前的网络IO模型都是并发的,也就是依旧是单线程处理,而Redis6.0之后就是并行了,当然这需要为Redis分配当前机器的CPU核心数。
总结:
IO多路复用是IO模型的一种,即经典的Reactor设计模式,有时也称为异步阻塞IO。
多路指的是多个socket连接,复用指的是复用一个线程。 多路复用主要有三种技术:select,poll,epoll。epoll是最新的也是目前最好的多路复用技术。采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络IO的时间消耗),且Redis在内存中操作数据的速度非常快(内存内的操作不会成为这里的性能瓶颈),主要以上两点造就了Redis具有很高的吞吐量。
下面这两张图可以帮助更好的理解IO多路复用