Redis 为什么快?IO多路复用(select,poll,epoll)

Redis 为什么快?

  1. Redis 的数据在内存中,所有运算都是内存级别的运算。
  2. Redis 是单线程的,避免了线程切换和加锁带来的损耗。
  3. Redis 使用 epoll 作为非阻塞 I/O 多路复用的实现,IO多路复用程序监听多个 socket,并将 socket 放到队列中,每次从队列里取出一个 socket 给事件分派器,事件分派器再把 socket 分派给对应的事件处理器进行处理,这些处理器都是纯内存操作,效率非常高,处理一个事件可能只需要几微秒。

Redis 模型结构:

  • Redis 内部有一个文件事件处理器,它是单线程的,由四个部分组成,分别是:IO 多路复用程序、socket、事件分派器和事件处理器,其中事件处理器又分为:连接应答处理器、命令请求处理器和命令回复处理器。

IO多路复用

fd_set 数组是存有 0 和 1 的位数组,fd 指文件描述符。
常用的IO多路复用模型有三种:select、poll、epoll。

  • select:它维护了一个数组结构 fd_set,调用 select 函数时,会从用户空间拷贝 fd_set 到内核空间,并监听是否有事件触发,有就通过无差别轮询的方式遍历找到事件触发的位置,然后执行相关的读或写操作。轮询的时间复杂度为 O(n)。

    • 缺点:内核对被监控的 fd_set 集合做了大小限制,最大为 1024 ;每次调用 select,都需要把 fd_set 集合从用户态拷贝到内核态,都需要在内核遍历 传递进来的所有 fd_set ,效率很低。
  • poll:与 select 类似,区别是它采用的是 poll_fd 数据结构实现了一个可变长的数组,没有了最大文件描述符数量的限制。

  • epoll:epoll 与 select 的不同之处在于,epoll 监听事件是否触发时,还设置了回调函数,如果事件触发,就执行回调函数,并将准备就绪的 fd 放到 readyList 中,而不需要轮询遍历所有的 fd_set 。并且 epoll 没有最大文件描述符数量的限制。在高并发情况下 epoll 能支持更多的连接。

epoll 中有三个函数:

  • epoll_create;用于创建 保存epoll文件描述符的空间
  • epoll_ctl:用于添加和删除监视对象的文件描述符
  • epoll_wait:等待文件描述符发生变化

你可能感兴趣的:(08,redis)