ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

从处理请求的核心流程谈一谈Redis到底是单线程还是多线程

2021-09-21 10:34:34  阅读:174  来源: 互联网

标签:单线程 Redis 文件事件 接字 多线程 客户端


从处理请求的核心流程谈一谈Redis到底是单线程还是多线程

随着Redis版本的不断更新,Redis在处理请求方面也在不断的优化,由单线程的概念逐渐引入了多线程的概念。那么Redis到底是单线程还是多线程呢?

在Redis 4.0版本之前,Redis完全是单线程,没有引入多线程这个概念。因为Redis是完全是基于内存操作的,通常情况下CPU不会是redis的瓶颈,于是就采用单线程模型处理请求,如果使用多线程的话,反而会变得更复杂,同时还涉及到了多线程的上下文切换,带来了额外的性能消耗。所以,Redis读写速度快,除了基于内存操作、优化了底层数据结构以外,单线程处理请求也是速度快的原因之一!

到了Redis 4.0版本时,才引入了多线程的概念,但是核心流程还是单线程的,这里核心流程指的是Redis正常处理客户端发送过来的请求,即接收命令 ==> 解析命令 ==> 执行命令 ==> 返回结果。而所谓的多线程并没有涉及到核心流程的处理,只是用来做一些后台处理,比如删除对象等。

在Redis 6.0的时候,又一次加强了多线程的概念,这个版本多线程会涉及到了核心流程Redis 6.0中多线程主要用于网络的I/O阶段,也就是接收命令和写回结果阶段,而执行命令阶段还是单线程串行执行。

所以,说Redis是单线的这个说法从执行命令阶段来看,是没毛病的!

之所以Redis单线程也很快,是因为:

  1. 完全是基于内存操作的
  2. 单线程避免了多线程上下文切换带来的额外消耗
  3. Redis对底层的数据结构做了优化
  4. I/O多路复用

接下来我们重点来讲讲Redis的I/O多路复用技术

我们要知道Redis服务器是一个事件驱动程序,是需要靠事件触发服务器对请求的处理操作。服务器需要处理的事件分为了两类:

  • 文件事件

    Redis服务器是通过套接字与客户端或者其它Redis服务器进行连接的,而文件事件实际上就是指的Redis服务器与客户端或者其它服务器之间的互相通信的一种抽象概述。服务器和客户端之间通信会产生相应的文件事件,服务器通过监听这些产生的文件事件来完成一系列网络通信操作。你可以理解为客户端发送请求给服务器,然后服务器监听到请求之后,处理请求并返回。

  • 时间事件

    顾名思义,Redis服务器的一些操作需要在特定的时间点才会触发执行,而时间事件就是对这种定时操作的一种抽象概述。

平时我们操作最多的就是文件事件,接下来我们主要来说说文件事件

**Redis基于Reactor模式(事件驱动模型)开发了自己的文件事件处理器。**由于文件事件处理器是单线程执行的,也就是我们之前说的执行命令阶段,所以说Redis是单线程模型是没问题的。

那么既然是单线程模型,那Redis是如何监听大量的客户端连接的呢?

Redis使用I/O多路复用技术实现了监听客户端大量连接,或者说监听大量的套接字。当被监听的套接字准备好执行连接应答、读取、写入、关闭等操作时,与操作相对应的文件事件也就产生了,Redis服务器会根据套接字目前阶段执行的操作来为套接字关联不同的文件事件处理器,来处理这些事件。虽然文件事件处理器以单线程方式运行,但通过使用IO多路复用技术来监听多个套接字,文件事件处理器既实现了高性能的网络通信模型,又可以很好的与redis服务器中其它同样以单线程方式运行的模块进行对接。

而这个文件事件处理器由4个部分组成:

  • 套接字(客户端与服务器之间的连接)
  • I/O多路复用程序(监听大量客户端连接的关键技术)
  • 文件事件分派器(socket映射到对应的文件处理器)
  • 事件处理器(连接、请求、回复、关闭等处理器)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lLruxLzV-1632190403889)(C:\Users\Jian\AppData\Roaming\Typora\typora-user-images\image-20210822102630124.png)]

其中I/O多路复用程序负责监听多个套接字,并向文件事件分派器传送产生了事件的套接字。尽管多个文件事件可能并发的发生,但是I/O多路复用程序会将所有产生事件的套接字都放到一个队列里面,然后通过这个队列,有序、同步、每次一个的将套接字发送给文件事件分派器。当一个套接字被对应所关联的事件处理器执行完成之后,I/O多路复用程序才会继续向文件事件分派器传送下一个套接字。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hPplmtyM-1632190403892)(C:\Users\Jian\AppData\Roaming\Typora\typora-user-images\image-20210822103317420.png)]

以上就是Redis单线程且高效的原因!

我们说在Redis 4.0版本的时候才引入了多线程的概念,但是多线程不涉及核心流程,直到Redis 6.0版本再次了多线程的概念,涉及到了核心流程。Redis 6.0版本加入多线程 I/O 之后,处理命令的核心流程如下:

  1. 连接应答

    当服务器监听到套接字连接时,主线程将该客户端连接放到全局等待读队列

  2. 读取数据:

    1)主线程将等待读队列的客户端连接通过轮询调度算法分配给 I/O 线程处理;

    2)同时主线程也会自己负责处理一个客户端连接的读事件;

    3)当主线程处理完该连接的读事件后,会自旋等待所有 I/O 线程处理完毕(这里就有点像Java中基于AQS框架实现的并发工具类CountDownLatch)

  3. 命令执行:

    主线程按照事件被加入全局等待读队列的顺序(保证了执行顺序是正确的),串行执行客户端命令,然后将客户端连接放到全局等待写队列

  4. 写回结果:

    跟等待读队列处理类似,主线程将等待写队列的客户端连接使用轮询调度算法分配给 I/O 线程处理,同时自己也会处理一个,当主线程处理完毕后,会自旋等待所有 I/O 线程处理完毕,最后清空队列。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rJM2ZCDh-1632190403894)(C:\Users\Jian\AppData\Roaming\Typora\typora-user-images\image-20210921100646235.png)]

我们可以看出来,Redis 6.0版本的多线程虽然涉及到了核心流程,但是命令执行阶段还是单线程串行执行的,只是在读取数据和写回结果这两个阶段采用了多线程I/O处理。说白了就是维护了两个队列,一个全局等待读队列,一个全局等待写队列,使得单线程转专注于命令的执行,由多线程处理读写操作,从而提高了I/O读写性能。

以上就是为什么说Redis又是多线程的原因!

标签:单线程,Redis,文件事件,接字,多线程,客户端
来源: https://blog.csdn.net/qq_39794062/article/details/120399138

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有