一、Redis为什么这么快
因为Redis采取了epoll模型,IO多路复用。同步非阻塞。
介绍epoll之前必须要先介绍下select和poll。明白select和poll的缺点后才能知道为什么epoll这么快。
1、源码
2、源码解析
// select(xx,读文件描述符集合,写文件描述符集合,异常文件描述符集合,超时时间),我们只需要关注读文件描述符集合,其他NULL不影响,因为有默认值。select(max+1, &rset, NULL, NULL, NULL)
rset其实就是fds(文件描述符的集合)。而select模型存储fds的方式是采取的bitmap,默认最大1024个。
1.select模型每次都直接将rset(也就是fds)全部拷贝到内核态,因为内核态速度比用户空间态快很多。2.如果没数据的话,select函数会阻塞,如果有数据的话会执行两步(1)将有数据的那个fd置位(也就是标记一下,代表这个fd有数据)(2)select函数不在阻塞,将继续往下执行。也就是整体遍历fds,找到有数据的那个fd读取数据做处理。他的fd不能重用,每一次都需要重新创建新的fds且将用户空间态的fds拷贝到内核态。(这个可以看上面while(1)的代码)
// 代表传入了5个pollfd这个结构体,超时时间是5000,poll整体就是围绕他的pollfd这个结构体来展开的poll(pollfds, 5, 5000)
poll的结构体是为了fd重复利用,不需要每次都拷贝到内核态用的。
revents:置位用的,如果某个fd有数据了,就把这个revents置位为POLLIN
2.3、执行流程
epoll的出现就是为了解决poll最后两个缺点的。
epoll_create 相当于创建白板epoll_ctl相当于往白板上写字,写的内容是一个fd、一个events结构体,events结构体跟pollfd的结构体很像。epoll_ctl执行完后就得到了epfd,epfd就是循环了五个fd-events放里面,每个fd都有events事件epoll_wait
2.2、执行流程
六、阻塞/非阻塞
用户进程通过调用select/poll/epoll去处理socket请求的时候, select/poll/epoll由于是阻塞的,所以导致用户进程阻塞;而select/poll/epoll处理的socket用的是非阻塞
比如三个redis-cli,假设2个redis-cli写入命令,select:那么select模型是轮询这三个redis-cli的fd,看哪个fd有消息,有的话读取处理消息。当他下次再写命令的时候还需要重新创建fd,然后复制到内核态然后再遍历全部。poll:那么poll模型是轮询这三个redis-cli的fd,看哪个fd有消息,有的话读取处理消息。下次再写入的时候还是遍历全局fd,看哪个fd有消息进行处理。省去了每次都创建新的fd且复制的过程。epoll:epoll就不轮询了,有消息进来后你通知我,我去处理你的消息,那些没消息的fd我不管。而且复制到内核态的过程我采取牛逼的技术让开销达到最小的极致。
关注小编,更多干货!