当前位置: 首页 > news >正文

高性能IO模型:为什么单线程Redis能那么快?

        我们通常说Redis是单线程,主要是指Redis的网络IO和键值对读写是由一个线程来完成的。这也是Redis对外提供键值存储服务的主要流程。

        但redis的其他功能,比如持久化、异步删除、集群数据同步等,其实是由额外的线程执行的。

Redis为什么用单线程?

  1. 多线程的开销会比较大,针对一些复杂的操作,需要考虑:多线程编程模式面临的共享资源并发访问控制问题
  2. 对于并发访问控制,如果只是采用粗粒度的互斥锁,那么即时增大了线程,也会导致大部分线程在等待获取访问共享资源的互斥锁,并行边串行,系统吞吐率并没有随着线程的增加而增加。
  3. 而且采用多线程开发一般会引入原语来保护共享资源的并发访问,这也会降低代码的易调试性和可维护性。

为了避免这些问题。redis直接采用了单线程模式。

单线程Redis为什么那么快

redis能使用单线程模型达到每秒数十万级别的处理能力,这是因为Redis多方面设计选择的一个综合结果:

  • redis大部分操作在内存上完成
  • 采用高效的数据结构,例如哈希表和跳表,他是实现高性能的一个重要原因。
  • 采用多路复用机制,使其在网络IO操作中能并发处理大量的客户端请求,实现高吞吐率。

在学习多路复用之前,要弄明白网络操作的基本IO模型和潜在的阻塞点。毕竟redis是采用单线程进行IO,如果线程被阻塞了,就无法进行多路复用了。

基本IO模型与阻塞点

simpleKV,最基本的一种实现是在一个线程中依次执行一系列操作。

以get请求为例,SimpleKV为了处理gei请求,需要监听客户端请求(bind/listen),和客户端建立连接(accept),从socket中读取请求(recv),解析客户端发送的请求(parse),根据请求类型读取键值数据(get),最后给客户端返回结果,即向socket中写回数据(send)。

redis基本IO模型

        在这里的网络IO操作中,有潜在的阻塞点,分别是:accept()和recv()。当Redis监听到一个客户端有连接请求,但一直未能成功建立连接时,会阻塞在accept()函数这里,导致其他客户端无法和Redis建立连接,同样,当Redis通过recv()从一个客户端读取数据时,如果数据一直没有到达,redis也会一直阻塞在recv()。

        这就导致redis整个线程阻塞,无法处理其他客户端请求,效率很低。幸运的是,socket网络模型本身支持非阻塞模式

非阻塞模式

        想要使用socket的非阻塞模式,就必须要了解三个函数的调用返回类型和设置模式。

        在socket模型中,不同操作调用后会返回不同的套接字类型。socket()方法会返回主动套接字,然后调用listen()方法,将主动套接字转化为监听套接字,此时可以监听来自客户端的了解请求。最后,调用accept()方法接收到达的客户端连接,并返回已连接套接字。

 redis套接字类型与非阻塞设置

         针对监听套接字,可以设置非阻塞模式:当redis调用accept()但一直未有连接请求到达时,redis线程可以返回处理其他操作,而不用一直等待。但要注意的是,调用accept()时,已经存在监听套接字了。

        虽然redis线程可以不用一直等待,但是总得有机制继续在监听套接字上等待后续连接请求,并在有请求是通知redis。

        类似的我们可以针对已连接套接字设置非阻塞模式:redis调用recv()后,如果已连接套接字上一直没有数据到达,redis同样可以返回处理其他操作。我们也需要有机制继续监听该已连接套接字,并在有数据达到时通知redis。

        这样才会保证redis线程,既不会像基本IO模型中一直在阻塞点等待,也不会导致redis无法处理实际到达的连接请求或数据。

        到此,可以继续了解linux上的IO多路复用机制。

基于多路复用的高性能IO模型

        Linux中IO多路复用机制是指一个线程处理多个IO流,就是我们经常听到的select/epoll机制。简单来说,在redis只运行单线程的情况下,该机制允许内核中,同时存在多个监听套接字和已连接套接字。内核会一直监听这些套接字上的连接请求或数据请求。一旦有请求到达,就会交给redis线程处理,这就实现了一个redis线程处理多个IO流的效果。

        下图是基于多路复用的Redis IO模型。图中的多个FD就是刚才所说的多个套接字。Redis网络框架调用epoll机制,让内核监听这些套接字。此时,redis线程不会阻塞在某一个特定的监听或者已连接套接字上。也就是说,不会阻塞在某一个特定的客户端请求处理上。正因为如此,Redis可以和多个客户端连接并处理请求,从而提升并发性。

基于多路复用的Redis高性能IO模型

        为了在请求到达时能通知到redis线程,select/epoll提供了基于事件的回调机制,即针对不同事件的发生,调用响应的处理函数。

        那么回调机制是怎么工作的呢?select/epoll一旦检测到FD上有请求到达时,就会触发响应的事件。

        这些事件会被放入到一个事件队列,redis单线程对这个事件队列不断进行处理。这样一来,redis无需轮询是否有请求实际发生,这就可以避免造成CPU资源浪费。同时,redis在对事件队列中的时间处理时,会调用相应的处理函数,这就实现了基于事件的回调。因为redis一直在对事件队列进行处理,所以能及时响应客户端请求,提升redis的响应性能。

以连接请求和读数据请求为例,具体解释:

        这两个请求分别对应accept事件和read事件,redis分别对这两个事件注册accept和get回调函数。当Linux内核监听到连接请求或者读数据请求时, 就会触发Accept事件和Read事件,此时,内核就会回调Redis响应的accept和get函数进行处理。

        这就像病人去医院看病。在医生实际诊断前,每个病人(等同于请求)都需要先分诊、测体温、登记等。如果这些工作都由医生来完成,医生的工作效率就会很低。所以,医院都设置了分诊台,分诊台会一直处理这些诊断前的工作(类似于Linux内核监听请求),然后再转交给医生做实际诊断。这样即使一个医生(相当于redis单线程),效率也能提升。

        需要注意的是,即使你的应用场景中部署了不同的操作系统,多路复用机制也是适用的。因为这个机制的实现有很多种,既有基于Linux 系统下的 select 和 epoll 实现,也有基于 FreeBSD 的 kqueue 实现,以及基于 Solaris 的 evport 实现,这样,你可以根据 Redis 实际运行的操作系统,选择相应的多路复用实现。

小结

        重点三个问题:redis真的只有单线程吗?、为什么用单线程?、单线程为什么这么快?

        现在我们知道了,redis单线程是指它对网络IO和数据读写的操作采用了单线程,而采用单线程的一个核心原因是避免多线程开发的并发控制问题。单线程的redis能高性能,跟多路复用的IO模型密切相关,因为这避免了accept()和send()/resc()潜在的网络IO操作阻塞点。

        另外redis的单线程是针对redis 5.0版本之前的。redis6.0中提出了多线程模型。

资料:03 高性能IO模型:为什么单线程Redis能那么快?.md

相关文章:

高性能IO模型:为什么单线程Redis能那么快?

我们通常说Redis是单线程,主要是指Redis的网络IO和键值对读写是由一个线程来完成的。这也是Redis对外提供键值存储服务的主要流程。 但redis的其他功能,比如持久化、异步删除、集群数据同步等,其实是由额外的线程执行的。 Redis为什么用单线…...

【数据集】中国各类水文专业常用数据集合集

1 水文气象数据 1.1 中国站点尺度天然径流量估算数据集(1961~2018年) 论文: J2022-High-quality reconstruction of China’s natural streamflow-缪驰远(北京师范大学地理科学学部) 研究内容&#xff1a…...

落枕、肩颈酸痛,用磁疗就可缓解!

睡觉之前还是好好的,一觉醒来脖子莫名疼痛,转都转不了,有时候连肩膀和上肢都难受,很可能是“落枕”了。 落枕引起的肩颈疼痛与多种因素有关,如颈肩部肌肉的过度使用、不良的睡眠姿势或颈肩部受寒湿空气的侵袭&#xff…...

一文教会你如何选择远程桌面(五大主流远程软件全面讲解)

写在前面 作为程序员的我们,随时随地写代码改代码是我们的日常。刚回到家,就被老板、产品经理cue是常有的事。基于这种情况,一般都会随身携带电脑,随时备战,不过每天背着电脑上下班非常不方便。因此资深程序员的解决方…...

【yolov5】yolov5训练自己的数据集全流程----包含本人设计的快速数据处理脚本

关于yolo应用时能用到的脚本集合,推荐收藏: https://chenlinwei.blog.csdn.net/article/details/127299428 1. 工程化快速yolo训练流程指定版(无讲解) 1.1 抽样数据集xml转txt输出量化分析 python make_dataset.pymake_dataset…...

leaflet 加载CSV数据,显示图形(代码示例046)

第046个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+leaflet中加载CSV文件,将图形显示在地图上。 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果; 注意如果OpenStreetMap无法加载,请加载其他来练习 文章目录 示例效果配置方式示例源代码(共74…...

百趣代谢组学资讯:槟榔的基因组为雌雄同株植物的性别决定提供见解

文章标题:The genome of Areca catechu provides insights into sex determination of monoecious plants 发表期刊:New Phytologist 影响因子:10.323 作者单位:海南大学 百趣生物提供服务:植物激素高通量靶标定…...

SSO单点登录 - 多系统,单一位置登录,实现多系统同时登录 学习笔记

(1)单点登录 多系统的前提下,单一位置的登录,会实现多系统同时登录的一种技术。 常出现在互联网应用和企业级平台中 如:京东 单点登录一般是用于互相授信的系统,实现单一位置登录,全系统有效的。 注意&#xff1a…...

图解LeetCode——剑指 Offer 32 - III. 从上到下打印二叉树 III

一、题目 请实现一个函数按照之字形顺序打印二叉树,即:第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。 二、示例 2.1> 示例1 提示: …...

【快排与归并排序算法】

作者:指针不指南吗 专栏:算法篇 🐾或许会很慢,但是不可以停下🐾 文章目录一、快速排序 ( Quick Sort )二、归并排序 ( Merge Sort )总结一、快速排序 ( Quick Sort ) 1.思路 找出一个分界点,随机的调整区间…...

面试官问我:说说你对JMM内存模型的理解?为什么需要JMM?

点个关注,必回关 随着CPU和内存的发展速度差异的问题,导致CPU的速度远快于内存,所以现在的CPU加入了高速 缓存,高速缓存一般可以分为L1、L2、L3三级缓存。基于上面的例子我们知道了这导致了缓存一致 性的问题,所以加入…...

工程管理系统源码之提高工程项目管理软件的效率

高效的工程项目管理软件不仅能够提高效率还应可以帮你节省成本提升利润 在工程行业中,管理不畅以及不良的项目执行,往往会导致项目延期、成本上升、回款拖后,最终导致项目整体盈利下降。企企管理云业财一体化的项目管理系统,确保…...

SpringBoot集成xxl-job实现

SpringBoot集成xxl-job实现 一、xxl-job介绍 xxl-job是一个分布式任务调度平台,核心设计目标是开发迅速、学习简单、轻量级、易扩展。源码:下载地址编译环境:Maven3、Jdk1.8、MySQL5.7 二、调度中心 初始化调度数据库,执行指定…...

欧几里得度量和余弦度量的可取消生物识别方案

欧几里得度量和余弦度量的可取消生物识别方案 便捷的生物识别数据是一把双刃剑,在为生物识别认证系统的繁荣铺平道路的同时,也带来了个人隐私问题。为了缓解这种担忧,提出了各种生物特征模板保护方案来保护生物特征模板免于信息泄露。现有提案…...

平板作为主机扩展屏的实现

网上有许多教程使用平板作为电脑的拓展屏,但是多数都是需要在电脑和平板上都装上服务器和客户端的软件才行,而且有些系统还没有对应的软件。 那有没有一种方法只需要在主机上运行一个软件,而平板上只需要扫个码就行呢? 答案是当然…...

HTTP和HTTPS有什么区别?如何实现网站的HTTPS?

细心的朋友会发现,我们在浏览网站时,有的网址以http开头,而有的网站却以https开头,那这两者之间有什么区别吗?http的网站如何能变成https呢?本文中科三方针对这个问题做下简单介绍。 什么是http&#xff1…...

Rockstar Games遭黑客攻击,《侠盗猎车手6》90个开发视频外泄

当地时间9月19日,视频游戏开发商Rockstar Games证实,其 热门游戏《侠盗猎车手6》(Grand Theft Auto)开发片段遭到黑客大规模窃取 ,这一泄露事件立即在游戏圈迅速传播。 据报道, 上周末黑客至少泄露了90个游…...

RabbitMQ-客户端源码之AMQPImpl+Method

AMQPImpl类包括AMQP接口(public class AMQImpl implements AMQP)主要囊括了AMQP协议中的通信帧的类别。 这里以Connection.Start帧做一个例子。 public static class Connection {public static final int INDEX 10;public static class Startextends…...

雅思经验(7)

我发现雅思阅读要命的不是难度,而是时间的把控。考试时间是总共一小时,但是要写三篇文章,之后总共40道题目,也就是说每篇文章平均是13.3道。但是他们很多人说,如果誊写答案需要花掉3、4分钟每篇,也就是说真…...

Ubuntu20.04 用 `hwclock` 或 `timedatectl` 设置RTC硬件时钟为本地时区

Ubuntu20.04用 hwclock 或 timedatectl 设置硬件时区为本地时区 可以用hwclock命令 sudo hwclock --localtime --systohc👆效果等同👇 , --localtime的简写是-l ; --systohc的简写是-w sudo hwclock -l -w也可以用timedatectl命令 👆效果等…...

P3 QT项目----记事本(3.8)

3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

06 Deep learning神经网络编程基础 激活函数 --吴恩达

深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...

Swagger和OpenApi的前世今生

Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章&#xff0c;二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑&#xff1a; &#x1f504; 一、起源与初创期&#xff1a;Swagger的诞生&#xff08;2010-2014&#xff09; 核心…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

稳定币的深度剖析与展望

一、引言 在当今数字化浪潮席卷全球的时代&#xff0c;加密货币作为一种新兴的金融现象&#xff0c;正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而&#xff0c;加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下&#xff0c;稳定…...

docker 部署发现spring.profiles.active 问题

报错&#xff1a; org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

使用LangGraph和LangSmith构建多智能体人工智能系统

现在&#xff0c;通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战&#xff0c;比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...

NPOI操作EXCEL文件 ——CAD C# 二次开发

缺点:dll.版本容易加载错误。CAD加载插件时&#xff0c;没有加载所有类库。插件运行过程中用到某个类库&#xff0c;会从CAD的安装目录找&#xff0c;找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库&#xff0c;就用插件程序加载进…...