Redis网络模型

一.Linux的IO读写模型

1.用户空间与内核空间

任何Linux发行版,其系统内核都是Linux。我们的应用都需要通过Linux内核与硬件交互。

Redis网络模型_第1张图片

2.Linux的IO模型

Linux系统为了提高IO效率,会在用户空间和内核空间都加入缓冲区:

写数据时,要把用户缓冲数据拷贝到内核缓冲区,然后写入设备

读数据时,要从设备读取数据到内核缓冲区,然后拷贝到用户缓冲区

Redis网络模型_第2张图片

二.Linux的IO模型

1.阻塞IO

用户读取数据时调用内核准备数据,以及内核拷贝数据到用户缓冲区这两个过程都需要阻塞等待

Redis网络模型_第3张图片

2.非阻塞IO

用户读取时,调用内核准备数据的过程中,若内核数据未就绪,直接给用户进程返回失败;在这个过程中用户进程会一直调用内核询问数据是否准备就绪。

第一阶段等待数据就绪非阻塞,但会一直调用内核询问是否就绪,忙等机制会造成CPU空转。第二阶段拷贝数据到用户空间仍然阻塞。

Redis网络模型_第4张图片

3.IO多路复用

阻塞IO与非阻塞IO的问题都在于,用户进程无法知道内核中数据是否就绪。

所以接下来就需要详细的来解决多路复用模型是如何知道到底怎么知道内核数据是否就绪的问题了

这个问题的解决依赖于提出的

文件描述符(File Descriptor):简称FD,是一个从0 开始的无符号整数,用来关联Linux中的一个文件。在Linux中,一切皆文件,例如常规文件、视频、硬件设备等,当然也包括网络套接字(Socket)。

通过FD,我们的网络模型可以利用一个线程监听多个FD,并在某个FD可读、可写时得到通知,从而避免无效的等待,充分利用CPU资源。

Redis网络模型_第5张图片

3.1 IO多路复用-select方式

其中select和pool相当于是当被监听的数据准备好之后,他会把你监听的FD整个数据都发给你,你需要到整个FD中去找,哪些是处理好了的,需要通过遍历的方式,去获取已经就绪的FD.

select方式最多能监听1024个FD.

Redis网络模型_第6张图片

3.2 IO多路复用模型-poll模式

与select对比:

  • select模式中的fd_set大小固定为1024,而pollfd在内核中采用链表,理论上无上限
  • 监听FD越多,每次遍历消耗时间也越久,性能反而会下降

Redis网络模型_第7张图片

3.3 IO多路复用模型-epoll模式

epoll模式使用红黑树存放需要监听的FD,使用链表存放已经就绪的FD。epoll模式下每次向红黑数中添加需要监听的FD时,都会设置一个回调函数,一旦FD就绪就会触发回调函数向链表中写入这个就绪的FD.

Redis网络模型_第8张图片

4.信号驱动IO

信号驱动IO是与内核建立SIGIO的信号关联并设置回调,当内核有FD就绪时,会发出SIGIO信号通知用户,期间用户应用可以执行其它业务,无需阻塞等待。

缺点就是:当有大量并发IO操作时,信号较多时,GIGIO函数会处理不及时;另外用户空间与内核空间频繁的信号交流会降低系统性能

Redis网络模型_第9张图片

5.异步IO

这种方式,不仅仅是用户态在试图读取数据后,不阻塞,而且当内核的数据准备完成后,也不会阻塞。

缺点是:当IO操作并发较高时,内核会积累很多的读写任务,会导致整个系统内存占用过多,最终导致系统崩溃。因此,想使用异步IO就需要对IO并发操作进行限流

Redis网络模型_第10张图片

三.模拟基于epoll的服务器端流程

服务器启动以后,服务端会去调用epoll_create,创建一个epoll实例,epoll实例中包含两个数据

1、红黑树(为空):rb_root 用来去记录需要被监听的FD

2、链表(为空):list_head,用来存放已经就绪的FD

创建好了之后,会去调用epoll_ctl函数,此函数会会将需要监听的数据添加到rb_root中去,并且对当前这些存在于红黑树的节点设置回调函数,当这些被监听的数据一旦准备完成,就会被调用,而调用的结果就是将红黑树的fd添加到list_head中去(但是此时并没有完成)

3、当第二步完成后,就会调用epoll_wait函数,这个函数会去校验是否有数据准备完毕(因为数据一旦准备就绪,就会被回调函数添加到list_head中),在等待了一段时间后(可以进行配置),如果等够了超时时间,则返回没有数据,如果有,则进一步判断当前是什么事件,如果是建立连接时间,则调用accept() 接受客户端socket,拿到建立连接的socket,然后建立起来连接,如果是其他事件,则把数据进行写出

Redis网络模型_第11张图片

四.Redis的网络模型

Redis网络模型_第12张图片

Redis网络模型_第13张图片

Redis网络模型_第14张图片

当我们的客户端想要去连接我们服务器,会去先到IO多路复用模型去进行排队,会有一个连接应答处理器,他会去接受读请求,然后又把读请求注册到具体模型中去,此时这些建立起来的连接,如果是客户端请求处理器去进行执行命令时,他会去把数据读取出来,然后把数据放入到client中, clinet去解析当前的命令转化为redis认识的命令,接下来就开始处理这些命令,从redis中的command中找到这些命令,然后就真正的去操作对应的数据了,当数据操作完成后,会去找到命令回复处理器,再由他将数据写出。

你可能感兴趣的:(redis,网络,数据库)