10、Redis单线程 VS 多线程

news2024/9/27 23:23:39

Redis单线程 VS 多线程

redis到底是单线程还是多线程?
IO多路复用听说过吗?
redis为什么快?

2、Redis为什么选择单线程?
这种问法其实并不严谨,为啥这么说呢?
Redis的版本很多3.x、4.x、6.x,版本不同架构也是不同的,不限定版本问是否单线程也不太严谨。
1 版本3.x ,最早版本,也就是大家口口相传的redis是单线程,阳哥2016年讲解的redis就是3.X的版本。
2 版本4.x,严格意义来说也不是单线程,而是负责处理客户端请求的线程是单线程,但是开始加了点多线程的东西(异步删除)。—貌似
3 2020年5月版本的6.0.x后及2022年出的7.0版本后,告别了大家印象中的单线程,用一种全新的多线程来解决问题。—实锤
在这里插入图片描述
5.0版本是直接升级到6.0版本,对于这个激进的升级,Redis之父antirez表现得很有信心和兴奋,
所以第一时间发文来阐述6.0的一些重大功能"Redis 6.0.0 GA is out!"
当然,Redis7.0后版本更加厉害

厘清⼀个事实我们通常说,Redis是单线程究竟何意?
Redis是单线程
主要是指Redis的网络IO和键值对读写是由一个线程来完成的,Redis在处理客户端的请求时包括获取 (socket 读)、解析、执行、内容返回 (socket 写) 等都由一个顺序串行的主线程处理,这就是所谓的“单线程”。这也是Redis对外提供键值存储服务的主要流程。
在这里插入图片描述
但Redis的其他功能,比如持久化RDB、AOF、异步删除、集群数据同步等等,其实是由额外的线程执行的。
Redis命令工作线程是单线程的,但是,整个Redis来说,是多线程的。

请说说演进变化情况?

Redis3.x单线程时代但性能依旧很快的主要原因

基于内存操作:Redis 的所有数据都存在内存中,因此所有的运算都是内存级别的,所以他的性能比较高;
数据结构简单:Redis 的数据结构是专门设计的,而这些简单的数据结构的查找和操作的时间大部分复杂度都是 O(1),因此性能比较高;
多路复用和非阻塞 I/O:Redis使用 I/O多路复用功能来监听多个 socket连接客户端,这样就可以使用一个线程连接来处理多个请求,减少线程切换带来的开销,同时也避免了 I/O 阻塞操作
避免上下文切换:因为是单线程模型,因此就避免了不必要的上下文切换和多线程竞争,这就省去了多线程切换带来的时间和性能上的消耗,而且单线程不会导致死锁问题的发生

Redis 是基于内存操作的,因此他的瓶颈可能是机器的内存或者网络带宽而并非 CPU,既然 CPU 不是瓶颈,那么自然就采用单线程的解决方案了,况且使用多线程比较麻烦。但是在 Redis 4.0 中开始支持多线程了,例如后台删除、备份等功能。

简单来说,Redis4.0之前一直采用单线程的主要原因有以下三个:
1 使用单线程模型是 Redis 的开发和维护更简单,因为单线程模型方便开发和调试;
2 即使使用单线程模型也并发的处理多客户端的请求,主要使用的是IO多路复用和非阻塞IO;
3 对于Redis系统来说,主要的性能瓶颈是内存或者网络带宽而并非 CPU。

3、既然单线程这么好,为什么逐渐又加入了多线程特性?

正常情况下使用 del 指令可以很快的删除数据,而当被删除的 key 是一个非常大的对象时,例如时包含了成千上万个元素的 hash 集合时,那么 del 指令就会造成 Redis 主线程卡顿。
这就是redis3.x单线程时代最经典的故障,大key删除的头疼问题,
由于redis是单线程的,del bigKey …
等待很久这个线程才会释放,类似加了一个synchronized锁,你可以想象高并发下,程序堵成什么样子?

如何解决?

比如当我(Redis)需要删除一个很大的数据时,因为是单线程原子命令操作,这就会导致 Redis 服务卡顿,
于是在 Redis 4.0 中就新增了多线程的模块,当然此版本中的多线程主要是为了解决删除数据效率比较低的问题的。
unlink key
flushdb async
flushall async
把删除工作交给了后台的小弟(子线程)异步来删除数据了。
因为Redis是单个主线程处理,redis之父antirez一直强调"Lazy Redis is better Redis".
而lazy free的本质就是把某些cost(主要时间复制度,占用主线程cpu时间片)较高删除操作,
从redis主线程剥离让bio子线程来处理,极大地减少主线阻塞时间。从而减少删除导致性能和稳定性问题。

在Redis 4.0就引入了多个线程来实现数据的异步惰性删除等功能,但是其处理读写请求的仍然只有一个线程,所以仍然算是狭义上的单线程。

4、redis6/7的多线程特性和IO多路复用

对于Redis主要的性能瓶颈是内存或者网络带宽而并非 CPU。最后Redis的瓶颈可以初步定为:网络IO。
在Redis6/7中,非常受关注的第一个新特性就是多线程。
这是因为,Redis一直被大家熟知的就是它的单线程架构,虽然有些命令操作可以用后台线程或子进程执行(比如数据删除、快照生成、AOF重写)。但是,从网络IO处理到实际的读写命令处理,都是由单个线程完成的。
随着网络硬件的性能提升,Redis的性能瓶颈有时会出现在网络IO的处理上,也就是说,单个主线程处理网络请求的速度跟不上底层网络硬件的速度,
为了应对这个问题:
采用多个IO线程来处理网络请求,提高网络请求处理的并行度,Redis6/7就是采用的这种方法。
但是,Redis的多IO线程只是用来处理网络请求的,对于读写操作命令Redis仍然使用单线程来处理。这是因为,Redis处理请求时,网络处理经常是瓶颈,通过多个IO线程并行处理网络操作,可以提升实例的整体处理性能。而继续使用单线程执行命令操作,就不用为了保证Lua脚本、事务的原子性,额外开发多线程互斥加锁机制了(不管加锁操作处理),这样一来,Redis线程模型实现就简单了

主线程和IO线程是怎么协作完成请求处理的

在这里插入图片描述
Unix网络编程中的五种IO模型

blocking IO - 阻塞IO
nonblocking IO - 非阻塞IO
IO multiplexing - IO多路复用
asynchronous IO - 异步IO
signal driven IO - 信号驱动IO

I/O 的读和写本身是堵塞的,比如当 socket 中有数据时,Redis 会通过调用先将数据从内核态空间拷贝到用户态空间,再交给 Redis 调用,而这个拷贝的过程就是阻塞的,当数据量越大时拷贝所需要的时间就越多,而这些操作都是基于单线程完成的。
在这里插入图片描述
从Redis6开始,就新增了多线程的功能来提高 I/O 的读写性能,他的主要实现思路是将主线程的 IO 读写任务拆分给一组独立的线程去执行,这样就可以使多个 socket 的读写可以并行化了,采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络IO的时间消耗),将最耗时的Socket的读取、请求解析、写入单独外包出去,剩下的命令执行仍然由主线程串行执行并和内存的数据交互。
在这里插入图片描述

结合上图可知,网络IO操作就变成多线程化了,其他核心部分仍然是线程安全的,是个不错的折中办法。
在这里插入图片描述
Redis6→7将网络数据读写、请求协议解析通过多个IO线程的来处理 ,
对于真正的命令执行来说,仍然使用主线程操作,一举两得,便宜占尽!!! o( ̄▽ ̄)d

Redis7将所有数据放在内存中,内存的响应时长大约为100纳秒,对于小数据包,Redis服务器可以处理8W到10W的QPS,
这也是Redis处理的极限了,对于80%的公司来说,单线程的Redis已经足够使用了。

在Redis6.0及7后,多线程机制默认是关闭的,如果需要使用多线程功能,需要在redis.conf中完成两个设置
在这里插入图片描述
在这里插入图片描述
1.设置io-thread-do-reads配置项为yes,表示启动多线程。
2。设置线程个数。关于线程数的设置,官方的建议是如果为 4 核的 CPU,建议线程数设置为 2 或 3,如果为 8 核 CPU 建议线程数设置为 6,线程数一定要小于机器核数,线程数并不是越大越好。

Redis自身出道就是优秀,基于内存操作、数据结构简单、多路复用和非阻塞 I/O、避免了不必要的线程上下文切换等特性,在单线程的环境下依然很快;
但对于大数据的 key 删除还是卡顿厉害,因此在 Redis 4.0 引入了多线程unlink key/flushall async 等命令,主要用于 Redis 数据的异步删除;
而在 Redis6/7中引入了 I/O 多线程的读写,这样就可以更加高效的处理更多的任务了,Redis 只是将 I/O 读写变成了多线程,而命令的执行依旧是由主线程串行执行的,因此在多线程下操作 Redis 不会出现线程安全的问题。
Redis 无论是当初的单线程设计,还是如今与当初设计相背的多线程,目的只有一个:让 Redis 变得越来越快。

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

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

相关文章

【2024】MySQL中常用函数和窗口函数的基本使用方式

MySQL中常用函数和窗口函数的基本使用方式 一、基础函数1、聚合函数:2、字符串函数:3、日期和时间函数4、数值函数5、条件函数 二、窗口函数(*OVER*) 一、基础函数 1、聚合函数: SELECT COUNT(*) FROM table_name;:计算表中的行…

在不破坏原有隔离状态的情况下,怎么实现网间数据安全摆渡?

随着网络技术的演进,网络攻击、数据窃取、数据泄露事件也愈发频繁,给企业造成损失和负面影响,企业数据防泄漏治理是大趋势,也是自身迫切需求。 2021年1月,中国农业银行因存在数据泄露风险、互联网门户网站泄露敏感信息…

数据接入体验再升级!TDengine 推出支持 MQTT 协议的数据接入功能

我们非常高兴地宣布,TDengine 企业版和 TDengine Cloud 正式推出重磅功能,这一功能主打无缝数据接入支持,旨在帮助用户彻底改善数据接入体验。作为一款创新性的解决方案,TDengine 企业版和 TDengine Cloud 可以直接将 MQTT 服务器…

使用YOLOV5训练自己的数据集时所遇到问题|PyYAML|KeyError

训练过程中: 1、attributeerror: module yaml has no attribute load 方法1: 如果另一个名为 yaml.py 的文件在 PyYaml 库之前出现在你的 sys.path 中,就会接收并导入该 yaml.py 文件。如将文件命名为 yaml.py。 import yaml 正在加载 ya…

<kernel>kernel 6.4 USB-之-port_event()分析

<kernel>kernel 6.4 USB-之-port_event()分析 kernel 6.4 USB系列文章如下: <kernel>kernel 6.4 USB-之-hub_event()分析 <kernel>kernel 6.4 USB-之-port_event()分析 本文是基于linux kerne…

把握数据要素,做数字化时代的弄潮儿

截至2022年6月,我国网民规模已经达到了10.51亿,人均上网时间达到了每周29.5个小时,并且这部分人群使用手机上网的比例为99.6%。如果把工作、睡眠以及其他的必要的时间算上的话,可以发现通过手机上网已经成为了人们日常中的一部分。…

渗透测试面试题汇总(附答题解析+配套资料)

注:所有的资料都整理成了PDF,面试题和答案将会持续更新,因为无论如何也不可能覆盖所有的面试题。 一、思路流程 1、信息收集 a、服务器的相关信息(真实ip,系统类型,版本,开放端口,…

Maven方式构建SpringBoot项目

目录 1、创建maven项目 2、添加springboot相关依赖 3、配置启动端口 4、修改APP文件 5、配置controller 6、启动应用 1、创建maven项目 项目如下&#xff1a; 2、添加springboot相关依赖 <parent><groupId>org.springframework.boot</groupId><arti…

iPhone电池缺陷落定,赔偿用户5亿美元逃不掉了

距离 iPhone 15 系列发布还有刚好一个月&#xff0c;大家准备好了吗&#xff1f; 钛合金边框、更好的相机 以及 Type-C 可能会成为一部分用户换机的理由。 当然这部分人中&#xff0c;肯定还有因为老机子电池不耐用了这一点的。 这可不&#xff0c;iPhone 电池健康度问题前不…

leetcode350. 两个数组的交集 II

简单题&#xff0c;10分钟秒杀 题目&#xff1a; 给你两个整数数组 nums1 和 nums2 &#xff0c;请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数&#xff0c;应与元素在两个数组中都出现的次数一致&#xff08;如果出现次数不一致&#xff0c;则考虑取较小值…

前端常用算法(一):防抖+节流

目录 第一章 防抖 1.1 防抖&#xff08;debounce&#xff09;简介 1.2 应用场景 1.3 实现思路 1.4 手撕防抖代码 第二章 节流 2.1 节流&#xff08;throttle&#xff09;简介 2.2 应用场景 2.3 实现思路 2.4 手撕节流代码&#xff08;方法&#xff1a;时间戳和计时器…

【100天精通python】Day38:GUI界面编程_PyQT从入门到实战(中)

目录 专栏导读 4 数据库操作 4.1 连接数据库 4.2 执行 SQL 查询和更新&#xff1a; 4.3 使用模型和视图显示数据 5 多线程编程 5.1 多线程编程的概念和优势 5.2 在 PyQt 中使用多线程 5.3 处理多线程间的同步和通信问题 5.3.1 信号槽机制 5.3.2 线程安全的数据访问 Q…

高光谱 | 矿物识别和分类标签数据制作、农作物病虫害数据分类、土壤有机质含量回归与制图、木材含水量评估和制图

本课程提供一套基于Python编程工具的高光谱数据处理方法和应用案例。 本课程涵盖高光谱遥感的基础、方法和实践。基础篇以学员为中心&#xff0c;用通俗易懂的语言解释高光谱的基本概念和理论&#xff0c;旨在帮助学员深入理解科学原理。方法篇结合Python编程工具&#xff0c;…

企业如何为服务器找到合适的托管机房?

企业的服务器在业务经营中扮演着很重要的角色&#xff0c;提供可靠的数据存储和备份功能、计算能力和软件支持、网络通信连接等功能&#xff0c;是企业运行中关键的组成部分。因此&#xff0c;企业的服务器需要得到妥善的保管&#xff0c;为它们选择一个合适的托管机房十分有必…

TCP/IP---网络层

一、网络层的主要功能 1、提供了通讯过程中&#xff0c;必须要使用的另一个地址&#xff1a;逻辑IP地址【ipv4、ipv6】 2、连接不同媒介类型【内网--外网&#xff08;intra -- inter&#xff09;】 3、根据运行的不同的路由协议&#xff0c;选择不同的最佳路径 4、在选择的最好…

Chatgpt小程序源码java版实践

ChatGPT的技术和资源背景 ChatGPT是一种基于大数据的语言模型&#xff0c;通过对大量数据进行计算&#xff0c;例如语言出现的概率和适用环境等。ChatGPT所使用的语言模型参数大约有2000亿个。由于ChatGPT的计算运行需要大量的计算机资源&#xff0c;因此在工程上要实现它是非…

nginx代理文件目录、下载站点

文章目录 前言一、访问站点配置二、添加登录权限功能1.密码生成2.配置nignx 三、路径加 / 如何区分1、proxy_pass末尾有斜杠2、proxy_pass末尾无斜杠3、proxy_pass包含路径&#xff0c;且末尾有斜杠4、proxy_pass包含路径&#xff0c;末尾无斜杠 四、文件路径 alias与root区别总…

反转链表(单向链表)

声明 该系列文章仅仅展示个人的解题思路和分析过程&#xff0c;并非一定是优质题解&#xff0c;重要的是通过分析和解决问题能让我们逐渐熟练和成长&#xff0c;从新手到大佬离不开一个磨练的过程&#xff0c;加油&#xff01; 原题链接 反转链表备战技术面试&#xff1f;力…

搭建Web服务器并用cpolar发布至公网访问

本地电脑搭建Web服务器并用cpolar发布至公网访问 文章目录 本地电脑搭建Web服务器并用cpolar发布至公网访问前言1. 首先在电脑安装PHPStudy、WordPress、cpolar2. 安装cpolar&#xff0c;进入Web-UI界面3. 安装wordpress4. 进入wordpress网页安装程序5. 利用cpolar建立的内网穿…

【OpenGauss源码学习 —— 执行算子(hash join 算子)】

执行算子&#xff08;hash join 算子&#xff09; 连接算子hash join算子ExecInitHashJoin函数HashJoinState结构体TupleTableSlot 结构体JoinState结构体PlanState结构体ExecInitHashJoin函数部分代码介绍 ExecHashJoin函数调试信息 ExecEndHashJoin函数ExecReScanHashJoin函数…