1 Redis中的单线程模型

提起Redis,我们经常会说其底层是一个单线程模型,但这是不严谨的。Redis 单线程指的是网络请求模块使用了一个线程,即一个线程处理所有网络请求,其他模块该使用多线程,仍会使用了多个线程。既然是单线程模型,那么CPU不是Redis的瓶颈。Redis的瓶颈最有可能是机器内存或者网络带宽

2 Redis中的单线程模型

Redis基于Reactor模式开发了自己的网络事件处理器,称之为文件事件处理器(File Event Hanlder)。文件事件处理器由SocketIO多路复用程序、文件事件分派器(dispather),事件处理器(handler)四部分组成,文件事件处理器的模型如下所示:

IO多路复用程序会同时监听多个socket,当被监听的socket准备好执行acceptreadwriteclose等操作时,与这些操作相对应的文件事件就会产生。IO多路复用程序会把所有产生事件的socket压入一个队列中,然后有序地每次仅一个socket的方式传送给文件事件分派器,文件事件分派器接收到socket之后会根据socket产生的事件类型调用对应的事件处理器进行处理。

文件事件处理器分为几种:

  • 连接应答处理器:用于处理客户端的连接请求;
  • 命令请求处理器:用于执行客户端传递过来的命令,比如常见的setlpush等;
  • 命令回复处理器:用于返回客户端命令的执行结果,比如setget等命令的结果;

事件种类:

  • AE_READABLE:与两个事件处理器结合使用。

    • 当客户端连接服务器端时,服务器端会将连接应答处理器与socketAE_READABLE事件关联起来;
    • 当客户端向服务端发送命令的时候,服务器端将命令请求处理器与AE_READABLE事件关联起来;
  • AE_WRITABLE:当服务端有数据需要回传给客户端时,服务端将命令回复处理器与socketAE_WRITABLE事件关联起来。

Redis的客户端与服务端的交互过程如下所示:

网络IO模型基本概念

内核态

内核态拥有完全的底层资源控制权限,可以执行任何的CPU指令,访问任何内存地址,其占有的处理机是不允许被抢占的。

用户态

用户程序是运行在操作系统之上,这些程序运行时称之为用户态,用户态下不能直接访问底层硬件和内存地址,只能通过委托系统调用的方式来访问底层硬件和内存。

用户态到内核态如何切换

从用户态切换到内核态有三种方式:

  • 系统调用:这是用户态主动要求切换到内核态的一种方式。用户进程通过系统调用申请使用操作系统提供的某些服务以便完成工作,比如,调用fork()指令实际上就是执行了一个创建新进程的系统调用。系统调用的机制其核心在于**使用了操作系统为用户特别开放的一个中断来实现的,例如Linuxint 80h中断;
  • 外设中断:当外围设备完成用户请求的操作后,会向CPU发出相应的中断信号。这时CPU会暂停执行下一条即将要执行的指令转而去执行与中断信号对应的处理程序。如果先前执行的是用户态下的指令,那么这个切换过程就是用户态转为内核态。比如硬盘读写操作完成,系统会切换到硬盘读写的中断处理程序中执行后续操作;
  • 异常:当CPU在执行运行处于用户态的程序时,发生了一些不可知的异常,这个时候就会触发由当前运行进行切换到处理此异常的内核相关程序中,也就是转到了内核态,比如缺页异常;

这三种是用户态切换到内核态的主要方式,系统调用是主动的,后面两种是被动的。

Linux的整体架构图如下所示:

同步/异步

同步/异步关注的是消息通信机制。

同步:所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回。等前一件做完了才能做下一件事。

异步:异步的概念和同步相对。当一个异步过程调用发出后,调用者若不能立刻得到结果,此时可以直接返回然后执行其他任务,等到获得了结果之后通过状态、通知或者回调等手段通知调用者。

同步、异步一般发生在不同的线程/进程之间,如Thread1Thread2是同步执行还是异步执行的。

阻塞和非阻塞

阻塞和非阻塞关注的是程序在等待调用结果时的状态。

阻塞: 阻塞调用是指调用返回之前,当前线程会被挂起,只有当调用得到结果后才返回。

非阻塞:与阻塞相反,非阻塞调用是指在不能立即得到结果之前,该函数不会将当前线程阻塞,而是立即返回。

五种 IO 模型

IO一般分为磁盘IO网络IO,这里我们主要关注网络IO。一次完整的网络IO过程如下所示:

从上图可以看出,数据无论从网卡到用户空间还是从用户空间到网卡都需要经过内核。

阻塞IO模型

当应用程序调用一个 IO 函数,其底层会委托操作系统的recvfrom()去完成,当数据还没有准备好时,revfrom会一直阻塞,等待数据准备好。当数据准备好后,从内核拷贝到用户空间,recvfrom 返回成功,IO函数调用完成。过程如下所示:

阻塞IO模型的优点是编程简单,但缺点是需要配合大量线程使用。应用进程没接收一个连接,就需要为此连接创建一个线程来处理该连接上的读写任务。

非阻塞IO模型

调用进程在等待数据的过程中不会被阻塞,而是会不断地轮询查看数据有没有准备好。当数据准备好后,将数据从内核空间拷贝到用户空间,完成IO函数的调用。等待数据的过程是非阻塞的,但数据拷贝时仍是阻塞的。过程如下所示:

非阻塞io的优点在于可以实现使用一个线程同时处理多个连接的需求,减少线程的大量使用。缺点在于要不断地去轮询检查数据是否准备好,比较耗费CPU

IO复用模型

为了解决非阻塞IO不断轮询导致CPU占用升高的问题,出现了IO复用模型。IO复用中,使用其他线程帮助去检查多个线程数据的完成情况,提高效率。

Linux中提供了selectpollepoll三种方式来实现IO复用。一个线程可以对多个IO端口进行监听,当有读写事件产生时会分发到具体的线程进行处理。过程如下所示:

IO复用只需要阻塞在selectpoll或者epoll,可以同时处理和管理多个连接。缺点是当selectpoll或者epoll 管理的连接数过少时,这种模型将退化成阻塞IO 模型。并且还多了一次系统调用:一次selectpoll或者epoll 一次recvfrom

4|4信号驱动IO模型

应用程序可以创建一个信号驱动程序SIGIO,当数据没有处理好时,应用程序继续运行,不会被阻塞。当数据准备好之后,操作系统向应用程序发送信号,之后信号驱动程序就会执行,在信号处理函数中调用 IO函数处理数据。过程如下所示:

信号驱动IO模型的优点在于非阻塞,缺点在于串行处理信号驱动程序,当前一个SIGIO没有被处理的情况下,后一个信号也不能被处理。在信号量大的时候会导致后面的信号不能被及时感知。

异步IO模型

相比于同步IO,异步IO不是顺序执行的。应用进程在执行aio_read系统调用之后,无论数据是否准备好,都会直接返回给用户进程,然后应用进程可以去做别的事情。当数据准备好之后,内核直接复制数据给用户进程,然后内核向进程发送通知。过程如下:

信号驱动IO模型中内核通知应用进程数据何时准备好,而在异步IO模型中内核将数据复制完成之后告知应用进程IO操作已完成。

在异步IO模型中,应用进程调用aio_read以及数据被拷贝到用户空间这两个过程都是非阻塞的。

5 网络IO模型总结

IO模型公有五种,前四种模型区别在于第一部分,即系统调用,但是第二部分都是一样的,即将数据从内核空间拷贝到用户空间这个过程,进程阻塞于redvfrom的调用。而最后一种,异步IO模型,在系统调用和数据拷贝过程都是非阻塞的。

03 Redis 网络IO模型简介相关推荐

  1. 【Netty】IO 模型简介 ( Netty 特点 | Netty 应用场景 | Java 三种 IO 模型 | BIO 模型 )

    文章目录 I . Netty 简介 II . Netty 应用场景 III . Java I/O 模型 IV . BIO 概念 V . BIO 开发流程 VI . BIO 实例 VII . BIO 模 ...

  2. 因为取了个快递我搞懂了五种网络IO模型

    五种网络IO模型 目录 前段时间,我有个朋友因为拿快递和家里闹别扭了,今天我就借这事来讲讲五大网络模型 阻塞IO模型 第一天: 刘:今天因为拿快递被我妈骂了一顿 我:说来听听 刘:我本来在家里打扫家务 ...

  3. Socket基础八:网络IO模型的应用

    Socket基础八:网络IO模型的应用 作者:刘磊 2020.4.27 参考书目:<Windows网络编程>刘琰等著 一.实验目的 1)掌握WindowsI/O操作的基本原理. 2)掌握阻 ...

  4. C++后台开发—网络IO模型与Reactor模式

    一.三种网络IO模型: 分类: BIO 同步的.阻塞式 IO NIO 同步的.非阻塞式 IO AIO 异步非阻塞式 IO 推荐视频: C++架构师学习地址:C/C++Linux服务器开发高级架构师/L ...

  5. 网络IO模型的介绍引出nginx的网络IO模型

    1. 什么是IO? 简单来说就是输入输出 2. 网络IO经历步骤 用户在获取网络资源是在进入网卡,经过网络七层模型将请求交给nginx用户进程 用户进程无法直接获取磁盘上的资源,会将请求获取什么资源翻 ...

  6. 五种网络IO模型详解

    一 IO操作本质 数据复制的过程中不会消耗CPU # 1 内存分为内核缓冲区和用户缓冲区 # 2 用户的应用程序不能直接操作内核缓冲区,需要将数据从内核拷贝到用户才能使用 # 3 而IO操作.网络请求 ...

  7. 大白话详解5种网络IO模型

    1 前言 我们都知道,为了实现高性能的通信服务器,BIO在高并发的情况下会出现性能急剧下降的问题,甚至会由于创建过多线程而导致系统OOM.因此在Java业界,BIO的性能问题一直被开发者所诟病,所幸的 ...

  8. 网络IO模型的深入浅出

    标题索引 追溯IO原因 网络数据流 网络IO模型 IO模型举例 追溯IO原因     从事项目多年来,有个问题一直困扰着我,但因种种原因一直没有翻阅资料去释怀,随着项目经历的增加.年龄的增长和责任的使 ...

  9. Linux 网络 IO 模型

    写在前面 本文主要介绍 Unix/Linux 下五种网络 IO 模型,但是.为了更好的理解下面提到的五种网络 IO 的概念,我们有必要先理清下面这几个概念. 用户空间与内核空间 一个计算机通常有一定大 ...

最新文章

  1. fabric 启动peer_编写 Fabric 链码的一般准则
  2. JDBC - 开发实例 - MVC模式
  3. 站长图卦:每天坚持搬砖 定有美好明天
  4. 2015第26周六《谁动了我的奶酪》书摘
  5. Go Mysql Driver 集成 Seata-Golang 解决分布式事务问题
  6. warning: pointer of type 'void *' used in arithmetic
  7. Golang开发的跨平台蜜罐平台HFish v0.6.4源码
  8. java两个数之间质数求法_Java程序显示两个间隔之间的质数
  9. mysql ndb 测试_mysql ndb笔记
  10. html新手练习软件,电脑打字指法练习 有以下软件是可以练习打字速度的:
  11. 2018年最好的8款杀毒软件
  12. selenium-禁止图片加载
  13. java环境安装教程_java环境搭建教程
  14. JAVA Swing界面美化 -付费界面库
  15. 用Wireshark简单分析HTTPS传输过程-抓包过程
  16. PC端微信登录实现流程
  17. Unity 制作小地图
  18. GPU-CUDA-图形渲染分析
  19. http协议学习系列
  20. 1079: 统计方形

热门文章

  1. unity闪现技能键制作之技能冷却
  2. Python基础之格式化输出
  3. 一次勒索解密的全经理(转载)
  4. ryzen服务器系列,amd ryzen 服务器
  5. 新手报道,请多关照!
  6. TP5.1 单入口多域名多模块设置
  7. jmeter中乱码问题解决办法
  8. Frida踩坑 can‘t decode byte 0xc0 in position 86 , can‘t decode byte 0xc0 in position 86
  9. Android分析破解-秒脱360加固大法
  10. c语言中rand()的作用,c语言中rand()函数怎么用? rand函数的用法