首页 > 数据库 >Redis之I/O多路复用模型实现原理

Redis之I/O多路复用模型实现原理

时间:2023-03-16 15:56:03浏览次数:32  
标签:socket 多路复用 模型 Redis 阻塞 服务端 客户端

本文内容基于 Redis 6.0 以前的版本编写,因为 6.0 之后 Redis 在网络处理这一块采用了多线程模式,但是 I/O 多路复用的模型还在,变化不大。本文有不当之处,大家轻喷!

Redis之I/O多路复用模型实现原理

Redis 的 I/O 多路复用模型有效的解决单线程的服务端,使用不阻塞方式处理多个 client 端请求问题。在看 I/O 多路复用知识之前,我们先来看看 Redis 的客服端怎么跟客服端建立连接的、单线程 socket 服务端为什么会存在 I/O 阻塞。

Redis客户端连接

Redis 通过监听一个 TCP 端口或者 Unix socket 的方式来接收来自 client 端的连接,当一个连接建立后,Redis 内部会进行以下一些操作:

  • 首先,客户端 socket 会被设置为非阻塞模式,因为 Redis 在网络事件处理上采用的是非阻塞多路复用模型。

  • 然后为这个 socket 设置 TCP_NODELAY 属性,禁用 Nagle 算法。

  • 然后创建一个可读的文件事件用于监听这个客户端 socket 的数据发送。

阻塞I/O

在 socket 连接中,一个服务器进程和一个客户端进行通信时,当一个 client 端向服务端写数据时,如果 client 端没有发送数据,那么服务端的 read 将一直阻塞,直到客户端 write 发来数据。在一个客户和服务器通信时没什么问题,当多个客户 与 一个服务器通信时,就存在问题了。如下图,两个客服端同时连接一个服务端进行写数据的时序图。

 

 

 

从上图可以看出一个服务器进程和多个客户端进程通信的问题:

  • (1) client1 和服务端建立连接后,服务端会一直阻塞于 client1,直到 client1 客户端 write 发来数据才开始后面的操作。服务端阻塞期间,即使其他客服端 client2 的数据提前到来,也不能处理 client2 客服端的请求。

  • (2) 有一个严重的问题就是,如果客户端 client1 一直没有 write 数据到来,那么服务端 service 会一直阻塞,不能处理其他客户的服务。

上面就是 Redis 通过 Unix socket 的方式来接收来自 client 端的连接存在的 I/O 阻塞问题,而 「I/O 多路复用」就是为了解决服务端一直阻塞等待某一个 client 的数据到来,即使其他client的数据提前到来,也不会被处理的问题。

I/O多路复用

为什么 Redis 中要使用 I/O 多路复用这种技术呢?因为 Redis 是跑在「单线程」中的,所有的操作都是按照顺序线性执行的,但是「由于读写操作等待用户输入 或 输出都是阻塞的」,所以 I/O 操作在一般情况下往往不能直接返回,这会导致某一文件的 I/O 阻塞导,致整个进程无法对其它客户提供服务。而 I/O 多路复用就是为了解决这个问题而出现的。「为了让单线程(进程)的服务端应用同时处理多个客户端的事件,Redis 采用了 IO 多路复用机制。」

这里**“多路”「指的是多个网络连接客户端,」“复用”**指的是复用同一个线程(单进程)。I/O 多路复用其实是使用一个线程来检查多个 Socket 的就绪状态,在单个线程中通过记录跟踪每一个 socket(I/O流)的状态来管理处理多个 I/O 流。如下图是 Redis 的 I/O 多路复用模型:

 

 

 

  1.  #1.文件描述符(file descriptor):
  2. Linux 系统中,把一切都看做是文件,当进程打开现有文件或创建新文件时,内核向进程返回一个文件描述符。可以理解文件描述符是一个索引,这样,要操作文件的时候,我们直接找到索引就可以对其进行操作了。我们将这个索引叫做文件描述符(file descriptor),简称fd。

如上图对 Redis 的 I/O 多路复用模型进行一下描述说明:

  • (1)一个 socket 客户端与服务端连接时,会生成对应一个套接字描述符(套接字描述符是文件描述符的一种),每一个 socket 网络连接其实都对应一个文件描述符。

  • (2)多个客户端与服务端连接时,Redis 使用 「I/O 多路复用程序」 将客户端 socket 对应的 FD 注册到监听列表(一个队列)中。当客服端执行 read、write 等操作命令时,I/O 多路复用程序会将命令封装成一个事件,并绑定到对应的 FD 上。

  • (3)「文件事件处理器」使用 I/O 多路复用模块同时监控多个文件描述符(fd)的读写情况,当 acceptreadwrite 和 close 文件事件产生时,文件事件处理器就会回调 FD 绑定的事件处理器进行处理相关命令操作。  

    • #例如:以 Redis 的 I/O 多路复用程序 epoll 函数为例

    • 多个客户端连接服务端时,Redis 会将客户端 socket 对应的 fd 注册进 epoll,然后 epoll 同时监听多个文件描述符(FD)是否有数据到来,如果有数据来了就通知事件处理器赶紧处理,这样就不会存在服务端一直等待某个客户端给数据的情形。
    • #(I/O多路复用程序函数有 select、poll、epoll、kqueue)
  • (5)整个文件事件处理器是在单线程上运行的,但是通过 I/O 多路复用模块的引入,实现了同时对多个 FD 读写的监控,当其中一个 client 端达到写或读的状态,文件事件处理器就马上执行,从而就不会出现 I/O 堵塞的问题,提高了网络通信的性能。

  • (6)如上图,Redis 的 I/O 多路复用模式使用的是 「Reactor 设置模式」的方式来实现。

「总结:」

  • (1) Redis 的 I/O 多路复用程序函数有 select、poll、epoll、kqueue。select 作为备选方案,由于其在使用时会扫描全部监听的文件描述符,并且只能同时服务 1024 个文件描述符,所以是备选方案。

  • (2) I/O 多路复用模型是利用 select、poll、epoll 函数可以同时监察多个流的 I/O 事件的能力,在空闲的时候,会把当前线程阻塞掉。当有一个或多个流有 I/O 事件时,就从阻塞态中唤醒,于是程序就会轮询一遍所有的流(epoll 是只轮询那些真正发出了事件的流),依次顺序的处理就绪的流,这种做法就避免了大量无用的等待操作。

 

标签:socket,多路复用,模型,Redis,阻塞,服务端,客户端
From: https://www.cnblogs.com/shoshana-kong/p/17222896.html

相关文章

  • Redis常用命令
    redis数据库一、概述:redis数据库是一个内存数据库,基于内存进行数据存储的,redis数据库访问速度特别快。因此,redis通常被用于缓存系统、存储大量活跃数据,可以极大地提......
  • Redis中是如何实现分布式锁的?
    分布式锁常见的三种实现方式:数据库乐观锁;基于Redis的分布式锁;基于ZooKeeper的分布式锁。Redis要实现分布式锁,以下条件应该得到满足:互斥性:在任意时刻,只有一个客户端......
  • 性能测试从零开始实施指南——场景模型篇
    转载:https://www.cnblogs.com/imyalost/p/11415691.html今年跳槽到一家电商企业,性能测试需要从零开始。在性能测试不断推动落地过程中,积累了一些从零开始的经验和教训,自己......
  • 安装redis
    redis安装brewsearchredis  brewinstallredis (这里安装的是redis的最新版本,因为没有@)执行完毕之后,就完成了redis的安装。redis服务默认是安装在`/usr/local/Ce......
  • Redis查询大key
    原文安装wget"https://pypi.python.org/packages/68/44/5efe9e98ad83ef5b742ce62a15bea609ed5a0d1caf35b79257ddb324031a/redis-2.10.5.tar.gz#md5=3b26c2b9703b4b56b30......
  • 推荐几款三维模型几何纠正处理软件
    PolyWorks:是一款功能强大的三维测量和几何纠正软件,能够对三维模型进行高精度的几何纠正,支持多种三维数据格式,包括点云、三角网格等。Geomagic:是一款专业的三维扫描和几何......
  • #认识Redis
    Redis(全称:RemoteDictionaryServer远程字典服务)是一个开源的使用ANSIC语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。它是......
  • Redis基础知识
    IO多路复用IO:I/O是Input输入/Output输出的简称,通常指数据在内部存储器(内存)和外部存储器(硬盘、优盘)或其他周边设备之间的输入和输出。  输入/输出是信息处理系统(计算机)......
  • 狂神--Redis-Docker启动脚本
    1.docker版本20dockerinfoClient:Context:defaultDebugMode:falsePlugins:app:DockerApp(DockerInc.,v0.9.1-beta3)buildx:BuildwithBuil......
  • Django应用之间模型字段关联(实现表与表解耦)
    serializers.SerializerMethodField和钩子方法结合,可以实现对ModelSerializer类的一些字段进行二次加工classtbl_group_case(models.Model):STATUS_NORMAL=0......