Redis线程模型 事件 Redis是单线程模型为什么效率还

「这是我参与11月更文挑战的第14天,活动详情查看:2021最后一次更文挑战」。
image.png

事件

Redis服务器是一个事件驱动程序,服务器需要处理两类事件,一个是文件事件,一个是时间事件。这里重点说下文件事件。

文件事件

Redis服务器通过socket与客户端进行连接。而文件事件就是就是对socket操作的抽象,服务端和客户端的通信会产生响应的文件事件,而服务器则通过监听并处理这些事件来完成一系列的网络通信操作。

Redis基于Reactor模式开发了自己的网络事件处理器,这个处理器被称为文件事件处理器。

  • 文件事件处理器使用I/O多路复用程序来同时监听多个socket,并根据socket目前执行的任务来为socket关联不同的事件处理器。
  • 当被监听的socket准备好执行连接应答,读取,写入,关闭等操作,与操作相对应的文件事件就会产生,这时文件事件处理器就会调用套接字之前关联好的事件处理器来处理这些事件。

之所以说Redis是单线程的,是因为文件事件处理器是以单线程方式运行,但通过I/O多路复用程序来监听多个套接字,文件事件处理器实现了高性能网络通信模型。

文件事件处理器构成

文件事件处理器由四个部分构成,分别是socket,I/O多路复用程序、文件事件分派器、事件处理。

每当一个sokcet准备好执行连接应答、写入、读取、关闭等操作,就会产生一个文件事件。一个服务通常会连接多个socket,所以多个文件事件有可能并发出现。

I/O多路复用程序负责监听多个socket,并向文件事件分派器传送产生了事件的socket。

I/O多路复用程序会将所有产生了事件的socket放入队列,通过这个队列,以有序、同步、每次一个socket方式向文件事件分派器传送socket。当一个socket产生的事件被处理完之后,才会继续向文件事件分派器传送下一个socket。

image.png

文件事件分派器会根据socket产生的事件类型调用相应的事件处理器。

Redis的I/O多路复用程序的所有功能都是通过包装常见的select、epoll、evport等多路复用函数库来实现的。

事件类型

I/O多路复用程序可以监听多个socket的ae_readable事件和ae_writable事件,这两类事件和socket对应关系如下:

  • 客户端对socket执行write操作,此时socket就会变得可读,就会产生as_readable事件
  • 当客户端对socket执行read操作,socket会变的可写,产生ae_writable事件。

如果一个socket同时产生这两中事件,文件事件分派器会优先处理ae_readable事件。

文件事件的处理器

文件事件对应有多个处理器,来实现不同的网络通信需求

  1. 连接应答处理器

这个处理器用于对连接服务器监听socket的客户端进行应答。

当有客户端请求连接时,socket就会产生ae_readable事件,引发连接应答处理器执行。

  1. 命令请求处理器

这个处理器负责从socket读取客户端发送的命令请求内容。

当客户端通过连接应答处理器连接到服务器后,服务器会将客户端socket的ae_readable事件和命令请求处理器进行关联,当客户端向服务器发送命令请求,socket就会产生ae_readable事件,引发命令请求处理器执行。

  1. 命令回复处理器

负责将服务器执行命令后得到的命令回复通过socket返回给客户端。

当服务器有命令回复需要传送给客户端的时候,服务器会将客户端socket的ae_writable事件和命令回复处理器进行关联,当客户端准备好接收服务器传回的命令回复时,会产生ae_writable事件,引发回复处理器执行。

一次完整的客户端和服务器连接事件示例

假设一个Redis服务器在运作,这个服务器的监听socket的ae_readable事件会处于监听状态之下,该事件对应的处理器为连接应答处理器。

如果这时一个Redis客户端向服务器发起连接,那么监听socket将产生ae_readable事件,触发连接应答处理器执行,会创建客户端socket,然后将ae_readable与请求处理器关联。

之后假设客户端向主服务器发送一个命令请求,客户端socket会产生ae_readable事件,引发命令请求处理器执行。

执行命令产生相应的命令回复,为了将这些命令回复传给客户端,会将客户端socket的ae_writable事件与命令回复处理器进行管理。当客户端尝试读取命令回复时,会产生ae_writable事件,触发命令回复处理器执行,当命令回复处理器将命令回复全部写入到socket,服务器就会解除客户端socket的ae_writable事件与命令回复处理器之间的关联。

image.png

Redis是单线程模型为什么效率还这么高?

纯内存访问:数据存放在内存中,内存的响应时间大约是100纳秒,这是Redis每秒万亿级别访问的重要基础。

非阻塞I/O:Redis采用epoll做为I/O多路复用技术的实现,再加上Redis自身的事件处理模型将epoll中的连接,读写,关闭都转换为了时间,不在I/O上浪费过多的时间。

单线程避免了线程切换和竞态产生的消耗。

Redis采用单线程模型,每条命令执行如果占用大量时间,会造成其他线程阻塞,对于Redis这种高性能服务是致命的,所以Redis是面向高速执行的数据库

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%