Redis的单线程模型和标准Reactor线程模型的关系

news2024/11/28 20:49:26

文章目录

  • Redis到底是不是单线程?
  • 标准Reactor线程模型
    • 单reactor单线程
    • 单reactor多线程
    • 多reactor多线程
  • redis6.0 之前的单线程模型
  • redis6.0 之后的单线程模型
    • 为什么redis最初选择的单线程网络模型?
    • 为什么redis6.0 io读写要用多线程?
  • Redis 6.0和Memcached多线程模型对比
  • 总结
  • 3种标准reactor模型的灵活应用
    • redis6.0 的reactor应用
    • dubbo的reactor应用

Redis到底是不是单线程?

我们都听说过redis是单线程的,但这么说并不准确。确切的说在redis4.0版本之前,redis是单线程的。
在redis 4.0为了防止耗时的命令阻塞线程,导致无法处理后续事件。引入了多线程来处理一些非阻塞命令。有:UNLINK、FLUSHALL ASYNC、FLUSHDB ASYNC等。备份aof、集群通信等模块是单独线程的。但是整个网络模型依然是单线程的,所以我们称之为单线程。
redis 6.0 就真正的在网络模型上加入多线程IO来解决网络IO的性能瓶颈。
此时IO读写是多线程的,执行命令依旧是单线程的。

标准Reactor线程模型

标准的reactor线程模型有3种:单reactor单线程、单reactor多线程、多reactor多线程。

单reactor单线程

Redis的单线程模型就是使用的经典的单线程Reactor模型。
我们先看看单线程的Reactor模型

在这里插入图片描述
消息处理流程:

Reactor对象通过select/poll/epoll等IO多路复用监控连接事件,收到事件后通过dispatcher事件分发器进行转发。
如果是连接建立的事件,则由acceptor接受连接,并创建Handler处理后续事件。
如果不是建立连接事件,则Reactor会分发调用Handler来响应。
Handler会完成read->业务处理->send的完整业务流程。

优点:

单线程运行,串行操作,不需要加锁,逻辑简单。
缺点:

仅用一个线程处理请求,对于多核资源机器来说是有点浪费的。
当处理读写任务的线程负载比较重,将会阻塞后续的事件处理,导致整体延迟变大。
应用:

Redis网络模型。(6.0版本以前)

单reactor多线程

在这里插入图片描述
单 Reactor 多线程也是只有一个 Reactor,与单线程的主要区别在于,使用多线程来进行业务逻辑的处理。
一个线程 + 一个线程池:

单线程:建立连接(Acceptor)和 监听accept、read、write事件(Reactor),复用一个线程。
工作线程池:处理事件(Handler),由一个工作线程池来执行业务逻辑,包括数据就绪后,用户态的数据读写。

具体流程:

主线程中,Reactor 对象通过 select 监听连接事件,收到事件后通过 dispatch 进行分发。
如果是连接建立的事件,则由 Acceptor 处理,Acceptor 通过 accept 接受连接,并创建一个 Handler 来处理连接后续的各种事件。
如果不是连接建立事件,则 Reactor 会调用连接对应的 Handler 来进行相应。
Handler 只负责响应事件,不进行业务处理,Handler 通过 read 读取到数据后,会发给 Processor 进行业务处理。
Processor 会在独立的子线程中完成真正的业务处理,然后将响应结果发给主进程的 Handler 处理,Handler 收到响应后通过 send 将响应结果返回给 client。
优点:能够充分利用多核多 CPU的处理能力

缺点:

多线程数据共享和访问比较复杂
Reactor 承担所有事件的监听和响应,只在主线程中运行,瞬间高并发时会成为性能瓶颈

多reactor多线程

在这里插入图片描述
比起单线程模型,它是将Reactor分成两部分:

mainReactor 负责监听server socket,用来处理网络IO连接建立操作,将建立的socketChannel指定注册给subReactor。 (只负责监听)
subReactor 主要做和建立起来的socket做数据交互和事件业务处理操作。通常,subReactor个数上可与CPU个数等同。一般是多个,这样的话,就可以充分利用多核的优势。 (负责IO读写和命令的执行)

区别于单线程Reactor模式,这种模式不再是单线程的事件循环,而是有多个线程subReactors各自维护一个独立的事件循环,由 mainReactor 负责接收新连接并分发给 subReactors 去独立处理,最后 subReactors 回写响应给客户端。

优点:

响应快,不必为单个同步时间所阻塞,虽然Reactor本身依然是同步的;
可扩展性,可以方便地通过增加Reactor实例个数来充分利用CPU资源;
缺点:

如果多个线程可能操作同一份数据,就涉及到底层数据同步的问题,则必然会引入某些同步机制,比如锁。增加了代码复杂度,同时增加了同步机制的开销。
应用:

Nginx, Netty, Swoole, Memcached就是使用的这个模型

redis6.0 之前的单线程模型

在这里插入图片描述
redis的网络事件处理器是基于Reactor模式,又叫做文件事件处理器。

文件事件处理器使用I/O多路复用来同时监听多个套接字,并根据套接字执行的任务关联到不同的事件处理器。
文件事件以单线程方式运行,但通过使用I/O多路复用程序来监听多个套接字,文件事件处理器实现了高性能的网络通信模型。
Redis 在处理客户端的请求时,包括接收(socket读)、解析、执行、发送(socket 写) 等都由一个顺序串行的主线程处理,这就是所谓的单线程。
其实就是应用的reactor单线程模型,从头到尾只有主线程处理io的链接、读写、业务执行。

redis6.0 之后的单线程模型

在这里插入图片描述
redis6.0之后的单线程模型,在负责io读写时使用了sub reactor多线程,在具体业务执行命令时还是返回由主线程串行执行。

为什么redis最初选择的单线程网络模型?

Redis 最初选择单线程网络模型的理由是:CPU 通常不会成为性能瓶颈,瓶颈往往是内存和网络,我们平时用多线程处理的业务一般比较耗时,比如业务的io读写、数据库操作,这是cpu是在闲着的,为了提高cpu利用率,我们才用多线程,但是redis本身就是直接操作的内存,io读写操作是很快的,cpu利用率很高,因此单线程足够了。

为什么redis6.0 io读写要用多线程?

CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存大小和网络带宽。
从Redis自身角度来说,因为读写网络的read/write系统调用占用了Redis执行期间大部分时间,瓶颈主要在于网络的 IO 消耗, 所以选择多线程IO来实现读写。主线程来执行Redis命令。

如果多线程包括了IO读写,解析和执行的整个过程,那么多线程需要面临线程安全的问题,Redis 6.0版本之前是没有考虑线程安全的,如果使用多线程来处理命令的执行,需要大量的改动来保证多线程的安全机制,实现更复杂。为了避免了不必要的上下文切换和竞争条件,多线程导致的切换而消耗 CPU,也不用考虑各种锁的问题,就让执行这一步只使用主线程。

总结就是:
将主线程 IO 读写任务拆分出来给一组独立的线程处理,使得多个 socket 读写可以并行化,但是 Redis 命令还是主线程串行执行。

Redis 6.0和Memcached多线程模型对比

相同点:

都采用了 Master-Worker 的线程的模型
不同点:

Memcached 执行主逻辑也是在 Worker 线程里,模型更加简单,实现了真正的线程隔离,通过各种锁机制来保证数据的线程安全。
而 Redis 把执行逻辑交还给 Master 线程,虽然一定程度上增加了模型复杂度,但也解决了数据的线程安全问题。

总结

  1. redis在4.0之前是纯单线程模型。
  2. 在4.0之后,aof备份、集群交互等操作由别的线程单独操作,但是网络通信执行命令模块还是单线程,应用的就是标准reactor单线程模型,由单一线程完成的网络连接、网络数据io读写、业务命令执行。
  3. 在6.0之后,网络通信的连接、业务执行命令还是由主线程完成的,但是期间的网络io数据读写是用了sub reactor多线程的。并不是标准的多reactor多线程模型。

3种标准reactor模型的灵活应用

标准的三种reactor线程模型,从单reactor单线程、单reactor多线程到多reactor多线程,也是在一步一步减少阻塞点的。从单reactor单线程到单reactor多线程减少了业务执行的阻塞点,从单reactor多线程到多reactor多线程减少了网络io读写等待的阻塞点。
实际上,很多中间件并没有完全按照标准的3种reactor模型,而是这3种模式的变种。

redis6.0 的reactor应用

redis6.0就是只在网络io读写时应用了多线程,在业务命令执行时又返回由主线程串行执行,综合应用了单reactor单线程模式和多reactor多线程模式,用多reactor多线程模式中的sub reactor,减少了网络io等待读写的阻塞,同时应用单reactor单线程执行业务命令,避免处理并发,避免加锁。

dubbo的reactor应用

dubbo在业务处理步骤时,也不是直接用sub reactor线程处理的,而是有专门的业务线程池,综合应用了单reactor多线程模式和多reactor多线程模式,用多reactor多线程模式中的sub reactor,减少了网络io等待读写的阻塞,同时应用单reactor多线程模式中的业务线程池,集中处理业务。关键就是用多线程减少阻塞点,灵活应用了3种reactor线程模型

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/646521.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

索尼RSV视频修复方法论视频文件修复时样本文件的三同

索尼RSV类的文件修复案例有很多,程序操作也很简单没什么可说的,这次这个索尼ILCE-7SM3的案例就是为了让大家更好的认识视频修复中我称之为“三同“的重要性,想要恢复的效果好必须要把准备工作做到位。 故障文件:45.1G RSV文件 故障现象: 索…

软件渗透测试是什么?软件产品哪种情况下需要做渗透测试?

随着互联网的普及,软件的开发方越来越多,但是随之而来的也是信息安全方面的问题。在软件开发过程中,安全问题一定要被重视,因为漏洞和安全问题一旦被黑客利用,会给公司和用户带来巨大的损失。为了避免这种情况的发生&a…

语音工牌在运营商智慧装维场景,有何应用价值?

客户精细化运营时代,如何做好客户服务体验,提升品牌美誉度和好感度,是众多企业开始思考的问题。 在运营商行业,上门装维和营业厅服务场景是企业与客户直接互动最多的地方。这个过程的服务质量直接影响到客户成交率、客户投诉率和…

软件测试金融银行项目如何测?从业务到测试实战,超细总结整理...

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 金融行业的业务特…

chatgpt赋能python:Python怎么打备注?让你的代码更加清晰易懂

Python怎么打备注?让你的代码更加清晰易懂 Python是一种流行的编程语言,可以用来构建不同类型的应用程序,从网站到数据分析。无论您是初学者还是经验丰富的开发人员,写清晰,易于理解的代码都是非常重要的,…

Linux之ACL权限

目录 Linux之ACL权限 场景 设定ACL权限 ACL权限管理命令 参数及作用 给用户和用户组添加ACL权限 案例 创建 目录 /project 的所有者和所属组其他人权限设定为 770 创建旁听用户pt,并赋予ACL权限rx 查看目录/project的ACL权限 验证pt 用户对于 /project 目录没有写权…

el-element-admin实现双路由菜单

需求: 1、输入用户名登录企业级菜单 2、点击企业级菜单中的首页,右边显示项目列表,点击某一行跳转到项目级菜单 注意: 企业级菜单和项目级菜单,后端分别给接口 具体实施: 1、点击面包靴首页的时候设置标记…

第14届蓝桥杯国赛真题剖析-2023年5月28日Scratch编程初中级组

[导读]:超平老师的《Scratch蓝桥杯真题解析100讲》已经全部完成,后续会不定期解读蓝桥杯真题,这是Scratch蓝桥杯真题解析第149讲。 第14届蓝桥杯Scratch国赛真题,这是2023年5月28日上午举办的全国总决赛,比赛仍然采取…

基于java springboot的图书管理系统设计和实现

基于java springboot的图书管理系统设计和实现 博主介绍:5年java开发经验,专注Java开发、定制、远程、指导等,csdn特邀作者、专注于Java技术领域 作者主页 超级帅帅吴 Java项目精品实战案例《500套》 欢迎点赞 收藏 ⭐留言 文末获取源码联系方式 文章目录…

load_dataset加载huggingface数据集失败

1. 一般的加载方式 from datasets import load_dataset dataset_dict load_dataset(cmrc2018)这种加载方式可能会显示因为连接问题导致失败,此时可以在hugging face里面找到对应的页面下载下来 然后改一下代码: from datasets import load_dataset d…

关于TFTP传输协议

TFTP(Trivial File Transfer Protocol,简单文件传输协议):实现客户端与服务器之间简单文件传输。小文件传输,端口:69。协议简单,易于实现。 缺点: 传输效率低对于超时机制没有明确说明每包长度…

华为OD机试真题B卷 JavaScript 实现【数组拼接】,附详细解题思路

一、题目描述 现在有多组整数数组,需要将它们合并成一个新的数组。 合并规则,从每个数组里按顺序取出固定长度的内容合并到新的数组中,取完的内容会删除掉,如果该行不足固定长度或者已经为空,则直接取出剩余部分的内…

第18章:逻辑架构

一、逻辑架构剖析 1.1服务器处理客户端请求 ①MySQL是典形的C/S架构,服务器端使用mysqld ②客户端进程向服务器进程发送SQL语句,服务器进程在向客户端进程发送处理结果。 查询请求演示图 查询请求详细图 1.2第1层:连接层 ①客户端访问My…

如何使用 NGINX Service Mesh 进行速率限制

原文作者:NGINX 原文链接:如何使用 NGINX Service Mesh 进行速率限制 转载来源:NGINX 官方网站 ​ NGINX 唯一中文官方社区 ,尽在 nginx.org.cn 无论 HTTP 请求是恶意的(暴力破解密码或 DDoS 攻击)还是正常…

day07--java高级编程:JDK8的新特性,JDK9的新特性,JDK10的新特性,JDK11的新特性,JDK15的新特性

1 JDK8的其它新特性 说明:一些8中的新特性在,java高级部分学习的同时顺便讲过了。 1.1 JDK8新特性的总体结构 1.2 Java 8新特性简介 1.3 Lambda表达式 1.3.1 出现背景 1.3.2 Lambda表达式的使用举例 package com.atguigu.java1;import org.junit.Tes…

2023年软件测试简历没有邀约?为什么?8类细节通通告诉你(附赠高薪简历)

求职不顺,没有邀约,大概率是你的简历出现了问题。 本篇文章列出高薪简历应该注意的细节,合计36处,涉及简历的八大组成部分。 现在就讲: 一、简历样式要求(3点要求) 1、简历格式,…

某游戏登录密码加密,webpack

注意:文章内容仅用于学习和技术交流,切勿做出违法的事情,如有侵权请联系我删除。 网址(今天的大冤种):aHR0cHM6Ly93d3cuZ205OS5jb20v 一,分析 从上面图片可以看到,他的密码是加密了…

FinGPT:以数据为中心的方法革新开源金融

FinGPT 由 AI4Finance Foundation 开发,是一种以数据为中心的工具,可使大型语言模型 (LLM) 的金融数据民主化。它旨在成为开放式金融的开源解决方案,旨在彻底改变金融业。本文将深入探讨 FinGPT 的复杂性、它的好处,以及它如何成为…

vscode使用latex环境无法编译,是否与anaconda环境冲突

Vscode使用latex环境无法编译,是否与anaconda环境冲突 在 VSCode 中使用 LaTeX 环境无法编译,可能与 Anaconda 环境冲突。这是因为 Anaconda 默认会将环境变量PATH 设置为 Anaconda 所在的路径,如果你使用的是 Anaconda 内置的 Python环境&am…

如何三分钟快速制作自定义ppt

目录 利用ChatGPTMindShow三分钟生成PPT 机器人 道合顺 莓用ai 百晓生 aichat 结合提词器以达到更好地提问效果: 更好地提问ChatGPT_常用prompt表_小黄同学LL的博客-CSDN博客 举个栗子: 利用ChatGPTMindShow三分钟生成PPT 提词:…