高性能IO模型:为什么单线程Redis能那么快?
我们通常说Redis是单线程,主要是指Redis的网络IO和键值对读写是由一个线程来完成的。这也是Redis对外提供键值存储服务的主要流程。
但redis的其他功能,比如持久化、异步删除、集群数据同步等,其实是由额外的线程执行的。
Redis为什么用单线程?
- 多线程的开销会比较大,针对一些复杂的操作,需要考虑:多线程编程模式面临的共享资源并发访问控制问题。
- 对于并发访问控制,如果只是采用粗粒度的互斥锁,那么即时增大了线程,也会导致大部分线程在等待获取访问共享资源的互斥锁,并行边串行,系统吞吐率并没有随着线程的增加而增加。
- 而且采用多线程开发一般会引入原语来保护共享资源的并发访问,这也会降低代码的易调试性和可维护性。
为了避免这些问题。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-缪驰远(北京师范大学地理科学学部) 研究内容:…...

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

一文教会你如何选择远程桌面(五大主流远程软件全面讲解)
写在前面 作为程序员的我们,随时随地写代码改代码是我们的日常。刚回到家,就被老板、产品经理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)单点登录 多系统的前提下,单一位置的登录,会实现多系统同时登录的一种技术。 常出现在互联网应用和企业级平台中 如:京东 单点登录一般是用于互相授信的系统,实现单一位置登录,全系统有效的。 注意:…...

图解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࿱…...

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命令 👆效果等…...

国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...

大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...

el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
基于matlab策略迭代和值迭代法的动态规划
经典的基于策略迭代和值迭代法的动态规划matlab代码,实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...

佰力博科技与您探讨热释电测量的几种方法
热释电的测量主要涉及热释电系数的测定,这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中,积分电荷法最为常用,其原理是通过测量在电容器上积累的热释电电荷,从而确定热释电系数…...

JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...