Redis的I/O多路复用机制

1. 为什么Redis要使用I/O多路复用机制呢?

因为Redis是单线程的,所有的操作命令都是顺序执行的,一旦有读写操作命令,等待用户输入或输出就会造成阻塞,所以I/O操作在一般情况下往往不能直接返回,这会导致某一操作的I/O阻塞导致整个进程无法进行其他操作,而I/O多路复用就是为了解决这个问题而出现的。

2. 什么是I/O多路复用?

I/O多路复用是指在单个线程中通过记录跟踪每一个socket(I/O流)的状态来管理多个I/O流。select、poll、epoll都是I/O多路复用的具体实现。I/O多路复用模型是建立在多路分离函数select基础之上的,使用select函数可以避免同步非阻塞IO模型中的轮询等待问题。
Redis的I/O多路复用机制
如上图所示,当用户线程发起read请求的时候,首先会将socket添加到select中,这时阻塞等待select函数返回。当数据到达时,select被**,select函数返回,此时用户线程才正式发起read请求,读取数据
从流程上看,使用select函数和同步阻塞模型没有太大的区别,甚至还多了添加监视socket以及调用select函数的额外操作,效率更差。但是,使用select以后的优势是用户可以在同一个线程内同时处理多个socket请求。用户可以注册多个socket,然后不断地调用select读取被**的socket,即可达到在同一个线程内同时处理多个I/O请求的目的。而在同步阻塞模型中,必须通过多线程的方式才能达到这个目的。
简单说,就是select函数是替当前的用户线程去等待数据到达,这个时候用户线程就空闲出来继续做别的事,而数据到达后,select函数会告诉用户线程数据到达了,用户线程可以发起read请求了,而数据已经达到了,就可以直接返回了,也就不存在阻塞了

3. 总结

“多路”是指多个网络连接,“复用”是指同一个线程,I/O多路复用模型是利用select、poll、epoll函数可以同时监测多个I/O流的能力,这些函数会轮询一遍所有的I/O流(epoll只轮询真正发出了事件的流),依次处理返回了数据,处于就绪状态的流,让单个线程高效地处理了多个连接请求,尽量减少网络IO的时间消耗,而且Redis是在内存中操作的,速度非常快。所以,Redis具有很高的吞吐量。