Redis为啥这么牛,速度快到飞起!

一、Redis为什么这么快

Redis之所以快,主要是因为它采用了epoll模型,实现了IO多路复用和同步非阻塞。在了解epoll之前,我们需要先了解select和poll。只有明白了它们的缺点,我们才能更深刻地理解为什么epoll如此高效。

源码是Redis快速运行的基础。rset其实就是fds(文件描述符的集合)。select模型在存储fds时采用的是bitmap方式,默认最大支持1024个fds。每次select模型都会将rset(也就是fds)全部拷贝到内核态,因为内核态的处理速度远快于用户空间态。这种方式存在一些问题。

如果没有数据,select函数会阻塞等待;如果有数据,则会进行两步操作:一是将有数据的fd置位,二是继续执行。每次都需要重新创建新的fds并复制用户空间态的fds到内核态,这是一个不小的开销。fds最大只支持1024个(虽然可以更改,但意义不大),而且每次都需要从头遍历到尾来找到有数据的fd,这是O(n)的时间复杂度问题。

poll模型为了解决select的一些问题而诞生。它的结构体设计允许fd的重复利用,不再需要每次都拷贝到内核态。当某个fd有数据时,可以将revents置位为POLLIN来表示。poll仍然需要遍历整个结构体来找到有数据的fd,仍然存在O(n)的时间复杂度问题。

epoll的出现就是为了解决poll的这些缺点。它将fd放到红黑树里,并且采取了“共享内存”的概念,不再需要每次都拷贝到内核态。当有数据到来时,epoll会进行置位重排,并通知用户进程进行处理。这样,epoll_wait只需要返回有数据的fd数量,用户进程就可以直接遍历这些fd,大大提高了效率。

二、阻塞与非阻塞

当我们使用select、poll或epoll处理socket请求时,它们是阻塞的,意味着用户进程会被阻塞直到有数据到来。这些模型处理的socket请求却是非阻塞的。

以Redis为例,如果有三个redis-cli连接,select模型需要轮询这三个连接的fd来查看哪个有消息;poll模型虽然省去了创建新的fd和复制的过程,但仍然需要轮询;而epoll则不再轮询,当有消息到来时直接通知用户进程处理,大大提高了效率。

Redis之所以快,是因为它采用了高效的IO多路复用技术和同步非阻塞模型,以及优化过的数据处理流程。

关注小编,更多技术干货等你来发现!