IO 多路复用
一个服务端进程可以同时处理多个套接字描述符
- 多路:多个客户端连接(连接就是套接字描述符)
- 复用:使用单进程就能够实现同时处理多个客户端的连接
其他方式是通过增加进程和线程的数量来并发处理多个套接字,免不了上下文切换的开销,而 IO 多路复用只需要一个进程就能够处理多个套接字,从而解决了上下文切换的问题。
其发展可以分 select->poll→epoll 三个阶段来描述。
select 就是轮询,在 Linux 上限制个数一般为 1024 个
poll 解决了 select 的个数限制,但是依然是轮询
epoll 解决了个数的限制,同时解决了轮询的方式
IO 多路复用在 Redis 中的应用
Redis 服务器是一个事件驱动程序, 服务器处理的事件分为时间事件和文件事件两类。
- 文件事件:Redis 主进程中,主要处理客户端的连接请求与相应。
- 时间事件:fork 出的子进程中,处理如 AOF 持久化任务等
由于 Redis 的文件事件是单进程,单线程模型,但是确保持着优秀的吞吐量,IO 多路复用起到了主要作用。
文件事件是对套接字操作的抽象,每当一个套接字准备好执行连接应答、写入、读取、关闭等操作时,就会产生一个文件事件。因为一个服务器通常会连接多个套接字,所以多个文件事件有可能会并发地出现。
IO 多路复用程序负责监听多个套接字并向文件事件分派器传送那些产生了事件的套接字。文件事件分派器接收 IO 多路复用程序传来的套接字,并根据套接字产生的事件的类型,调用相应的事件处理器。示例如图所示
由于 Redis 的文件事件是单进程,单线程模型,但是确保持着优秀的吞吐量,IO 多路复用起到了主要作用。
文件事件是对套接字操作的抽象,每当一个套接字准备好执行连接应答、写入、读取、关闭等操作时,就会产生一个文件事件。因为一个服务器通常会连接多个套接字,所以多个文件事件有可能会并发地出现。
IO 多路复用程序负责监听多个套接字并向文件事件分派器传送那些产生了事件的套接字。文件事件分派器接收 IO 多路复用程序传来的套接字,并根据套接字产生的事件的类型,调用相应的事件处理器。示例如图所示
Redis 的 IO 多路复用程序的所有功能都是通过包装常见的 select、poll、evport 和 kqueue 这些 IO 多路复用函数库来实现的,每个 IO 多路复用函数库在 Redis 源码中都有对应的一个单独的文件。
Redis 为每个 IO 多路复用函数库都实现了相同的 API,所以 IO 多路复用程序的底层实现是可以互换的。如图:
Redis 把所有连接与读写事件、还有我们没提到的时间事件一起集中管理,并对底层 IO 多路复用机制进行了封装,最终实现了单进程能够处理多个连接以及读写事件。这就是 IO 多路复用在 redis 中的应用。