select:调用开销大(需要复制集合);集合大小有限制;需要遍历整个集合找到就绪的描述符;poll:poll 采用数组的方式存储文件描述符,没有最大存储数量的限制;epoll:调用开销小(不需要复制);集合大小无限制。
一、epoll和select和poll的区别
三者对比
- select:调用开销大(需要复制集合);集合大小有限制;需要遍历整个集合找到就绪的描述符
- poll:poll 采用数组的方式存储文件描述符,没有最大存储数量的限制,其他方面和 select 没有区别
- epoll:调用开销小(不需要复制);集合大小无限制;采用回调机制,不需要遍历整个集合
select、poll 都是在用户态维护文件描述符集合,因此每次需要将完整集合传给内核;epoll 由操作系统在内核中维护文件描述符集合,因此只需要在创建的时候传入文件描述符。
此外 select 只支持水平触发,epoll 支持边缘触发。
适用场景
当连接数较多并且有很多的不活跃连接时,epoll 的效率比其它两者高很多。当连接数较少并且都十分活跃的情况下,由于 epoll 需要很多回调,因此性能可能低于其它两者。
延伸阅读:
二、Redis 的线程模型是什么
Redis是一个单线程的工作模型,使用 I/O 多路复用来处理客户端的多个连接。为什么 Redis 选择单线程也能效率这么高?
I/O 设备(如磁盘、网络)等速度远远慢于 CPU,因此引入了多线程技术。当一个线程发起 I/O 请求时,先将它挂起,切换到别的线程;当 I/O 设备就绪时,再切换回该线程。总之,多线程技术是为了充分利用 CPU 的计算资源,适用于下层存储慢速的场景。
而 redis 是纯内存操作,读写速度非常快。所有的操作都会在内存中完成,不涉及任何 I/O 操作,因此多线程频繁的上下文切换反而是一种负优化。Redis 选择基于非阻塞 I/O 的 I/O 多路复用机制,在单线程里并发处理客户端的多个连接,减少多线程带来的系统开销,同时也有更好的可维护性,方便开发和调试。
不过 redis 在最新的几个版本中也引入了多线程,目的是:
- 异步处理删除操作。当删除超大键值对的时候,单线程内同步地删除可能会阻塞待处理的任务
- 应对网络 I/O 的场景,网络 I/O 是慢速 I/O。redis6 吞吐量提高了 1 倍