Redis三种监听模式区别:

1.Redis网络模型之select

1.1 select方式首先确定需要监听fd(文件描述符)是多少,比如fd是1 3 5,然后将这些fd放入对应的fd数组,这里的fd数组是1024个比特位,比如1 3 5,就代表将1 3 5号比特位的值填充为1。

1.2 将fd数组从用户空间拷贝到内核空间,内核空间就负责检索传过来的数组,一一遍历哪些fd已经就绪,如果都没有就绪,那么用户空间那边就会阻塞等待,等到有fd已经就绪,假设这里是1号就绪,则将fd数组的1号比特位置为1,其余的比如3 5就置为0,然后再次拷贝回用户空间,用户空间根据传回来的fd数组进行遍历,就知道哪些fd已经准备就绪,然后进行相关操作

2.Redis网络模型之poll

2.1 poll模式对select模式做了简单的改进,但是性能提升不大,IO流程如下:

① 创建pollfd数组,向其中添加关注的fd信息,数组大小自定义

② 调用poll函数,将polld数组拷贝到内核空间,转链表存储,无上限

③ 内核遍历fd,判断是否就绪

④ 数据就绪或者超时后,拷贝pollfd数组到用户空间,返回就绪fd数量n

⑤ 用户进程判断n是否大于0

⑥ 大于0则遍历pollfd数组,找到就绪fd,然后执行相关操作

2.2 poll与select对比:

① select模式中的fd数组固定为1024,而pollfd在内核中采用链表,理论无上限

② 监听的fd越多,每次遍历消耗的时间也越久,性能反而会下降

3.Redis网络模型之epoll

分别有三个函数 epoll_create,epoll_ctl,epoll_wait

3.1 epoll_create函数:

用户线程调用这个函数,首先会在内核空间中,创建一个eventpoll结构体(其句柄为epfd),这个结构体里面存了两个结构,一个是红黑树,用来记录要监听的FD,另一个是链表,用来记录就绪的FD,一开始这两个都是空的

3.2 epoll_ctl函数:

用户线程调用这个函数,首先会将要监听的FD放到红黑树中,并且设置回调函数ep_poll_callback,一旦触发,则会将FD放到就绪列表中

3.3 epoll_wait函数:

用户线程调用这个函数,会检查就绪列表是否有元素,不为空则返回就绪的FD的数量,同时将就绪列表中的数据拷贝到在用户空间创建的epoll_event中(看图中的数据结构),然后根据就绪的FD进行对应的操作。