Redis是单线工作的,但他为什这么快呢?
多路IO机制是什么?有几种实现方式?他们的区别是什么?
为什么这么快:
基于内存操作、专门设计的数据结构、单线程没有线程切换开销、多路IO复用机制
多路IO复用是什么:
一个redis服务端可以同时处理多个客户端请求,每个请求都有一个socket。多路指的是多个IO流,
复用复用的redis单线程。
操作系统提供了select、poll、epoll三种多路IO复用机制,他们可以用来监控多个IO流,当有IO就绪时
唤醒进程进行处理。
与多线程、进程相比,多路IO复用不用开辟多个线程、进程,减少了系统开销
流:可以进行IO操作的对象,如socket等
每个流都有一个文件描述符。select\poll\epoll可以用来监控这些文件描述符是否就绪,就绪时唤醒线程进行处理。
select\poll\epoll是系统调用,内核可以知道哪些流就绪了,内核可以调度线程。
非阻塞IO、阻塞IO
阻塞:
select最多可以处理1024个文件描述符,它只通知有就绪的流,还需要程序每次去遍历来确定哪个流就绪了,
这样当每次只有少量流就绪时,就会浪费很多时间。
poll与select相比可处理的文件描述符的数目没有限制,其它缺点都具有。
epoll,解决了每次需要遍历流的问题,且不需要文件描述符在用户态和内核态之间的来回复制,只需要复制
一次就可以了。它每次返回就绪的流,直接处理就可以了。
poll和select的缺点:包含大量文件描述符的数组被整体复制于用户态和内核的地址空间之间,而不论这些文件描述符是否就绪,它的开销随着文件描述符数量的增加而线性增大
从select那里仅仅知道了,有I/O事件发生了,但却并不知道是那几个流(可能有一个,多个,甚至全部),我们只能无差别轮询所有流,找出能读出数据,或者写入数据的流,对他们进行操作。
epoll可以理解为event poll,不同于忙轮询和无差别轮询,epoll之会把哪个流发生了怎样的I/O事件通知我们。此时我们对这些流的操作都是有意义的。
select的几大缺点:
(1)每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大
(2)同时每次调用select都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也很大
(3)select支持的文件描述符数量太小了,默认是1024
网友评论