1、IO
多路复用
select
就是轮询,在Linux上限制个数一般为1024个;poll
解决了select的个数限制,但是依然是轮询;epoll
解决了个数的限制,同时解决了轮询的方式。
2、IO
多路复用在Redis
中的应用
Redis 服务器是一个事件驱动程序, 服务器处理的事件分为时间事件和文件事件两类。
- 文件事件:
Redis
主进程中,主要处理客户端的连接请求与相应。 - 时间事件:
fork
出的子进程中,处理如AOF
持久化任务等。
由于Redis
的文件事件是单进程,单线程模型,但是确保持着优秀的吞吐量,IO
多路复用起到了主要作用。
2.1、文件事件
文件事件是对套接字操作的抽象,每当一个套接字准备好执行连接应答、写入、读取、关闭等操作时,就会产生一个文件事件。因为一个服务器通常会连接多个套接字,所以多个文件事件有可能会并发地出现。
IO
多路复用程序负责监听多个套接字并向文件事件分派器传送那些产生了事件的套接字。文件事件分派器接收IO
多路复用程序传来的套接字,并根据套接字产生的事件的类型,调用相应的事件处理器。示例如图所示:
2.2、文件处理器
Redis
的IO
多路复用程序的所有功能都是通过包装常见的select
、poll
、evport
和kqueue
这些IO
多路复用函数库来实现的,每个IO
多路复用函数库在Redis源码中都有对应的一个单独的文件。
Redis
为每个IO
多路复用函数库都实现了相同的API
,所以IO
多路复用程序的底层实现是可以互换的。如图:
3、总结
Redis 6.0
之后的版本开始选择性使用多线程模型。
Redis
选择使用单线程模型处理客户端的请求主要还是因为 CPU
不是 Redis
服务器的瓶颈,使用多线程模型带来的性能提升并不能抵消它带来的开发成本和维护成本,系统的性能瓶颈也主要在网络 I/O
操作上;
而 Redis
引入多线程操作也是出于性能上的考虑,对于一些大键值对的删除操作,通过多线程非阻塞地释放内存空间也能减少对 Redis
主线程阻塞的时间,提高执行的效率。
凡事不能有绝对,寻找到适中的平衡点最重要!