Redis非阻塞单线程IO

  2019-8-21 


Redis的网络事件处理器,叫做【文件事件处理器】。它是【非阻塞】、【单线程】的,采用【IO多路复用机制】来同时监听多个Socket,根据Socket上的事件类型来选择对应的【事件处理器】来处理这个事件。所以说【Redis是单线程的模型】

单线程指的是【网络请求模】块使用了一个线程,即一个线程处理所有网络请求,借由此点,依然可以做到请求处理的高并发,只是其IO处理底层是单线程程序)

原理

img

文件事件处理器组成结构包括①多个Socket、②IO多路复用程序、③文件事件分派器、④事件处理器(命令请求处理器(read)、命令回复处理器(write)、连接应答处理器(accept)等)

  1. IO多路复用程序会监听多个 Socket
  2. Socket产生AE_READABLE事件时,它就会将该Socket事件放入一个队列中排队
  3. 每次从队列中取出一个 Socket 给事件分派器
  4. 事件分派器根据当前Socket产生的事件(见下),把 Socket 关联不同的事件处理器
  5. 【一个 Socket 的事件处理完之后】,IO多路复用程序才会将队列中的下一个 Socket 给事件分派器。(所以是单线程

(一个Socket事件处理完的结果会存放在一个回复队列中,待命令回复事件处理器来取出返回)

Socket产生的事件:

一个Socket对应一个客户端,可以产生多个事件

①当Socket可读时,客户端对redis执行read、write、close、connect操作,会产生AE_READABLE事件,可以理解为服务器可以读指令了

②当Socket可写时,客户端对redis执行read操作,会产生AE_WRITABLE事件,可以理解为服务器可以返回数据了

为什么是非阻塞的呢?多路复用:那么一个IO程序可以同时处理多个Socket请求(以上机制实现)

非阻塞:read/write失败就立即返回,执行下一条语句

ATT:一切对Redis的IO都是采用Redis的线程IO模型,即使客户端与服务端都是本机也是这样访问,实际上本地的网络数据流也是靠网卡和端口驱动

一次流程举例

  1. 在 Redis 启动初始化的时候,Redis 会将连接应答处理器跟 AE_READABLE 事件关联起来,接着如果一个客户端跟Redis发起连接,此时会产生一个 AE_READABLE 事件,然后由连接应答处理器来处理跟客户端建立连接,创建客户端对应的 Socket,同时将这个 Socket 的 AE_READABLE 事件跟命令请求处理器关联起来。

  2. 当客户端向Redis发起请求的时候(不管是读请求还是写请求,都一样),首先就会在 Socket 产生一个AE_READABLE 事件,然后由对应的命令请求处理器来处理。这个命令请求处理器就会从Socket中读取请求相关数据,然后进行执行和处理。

  3. 接着Redis这边准备好了给客户端的响应数据之后,就会将Socket的AE_WRITABLE事件跟命令回复处理器关联起来,当客户端这边准备好读取响应数据时,就会在 Socket 上产生一个 AE_WRITABLE 事件,会由对应的命令回复处理器来处理,就是将准备好的响应数据写入 Socket,供客户端来读取。命令回复处理器写完之后,就会删除这个 Socket 的 AE_WRITABLE 事件和命令回复处理器的关联关系。(仅命令回复处理器会有这个操作)

总结Redis即使是单线程也高效率(高QPS)的原因

  1. Redis的数据是存放在RAM中的,IO速度比磁盘IO不知道高得多

  2. 非阻塞的IO复用机制(本文)

    多路复用,那么一个IO程序可以同时处理多个Socket请求

  3. 单线程,避免了多线程频繁上下文切换的开销(本文)


且听风吟