关于redis单线程和IO多路复用的理解

news2025/1/25 4:30:33

首先,Redis是一个高性能的分布式缓存中间件。其复杂性不言而喻,对于Redis整体而言肯定不是只有一个线程。

我们常说的Redis 是单线程,主要是指 Redis 在网络 IO和键值对读写是采用一个线程来完成的,这也是 Redis 对外提供键值存储服务的核心流程。但对于 Redis 的其他功能来说,比如持久化、异步删除、集群数据同步等,其实都是由额外的线程执行的。
关于redis有几个基本的说辞:

 - 单线程
 - 基于内存操作,速度快
 - I/O 多路复用
 这里简单分析一下

单线程

单线程的优势:

  • 使用单线程可以避免频繁的上下文切换
  • Redis 中有各种类型的数据操作,甚至包括一些事务处理,如果采用多线程,还可能因为加锁导致软件复杂度提升,更有可能会因为加解锁,甚至出现死锁,造成的性能损耗,所以使用单线程反而性能会更好

其实是当出现多线程同时在操作一个共享的资源时,我们为了保证结果的正确性,我们需要有额外的开销来保证,如锁。当有锁出现了,我们就需要在考虑在什么时候需要获取锁,释放锁,其中就需要记录锁的状态,可想而知,性能就会下降。这就是多线程模式在面临高并发场景下共享资源的访问问题。

单线程为什么还可以这么快

 实现高性能的一个方面是 Redis 是基于内存操作,它内部高效的数据结构,如跳表,quicklist,listpack,哈希表等,还有就是 Redis 采用了 I/O多路复用机制,从而保障在网络 I/O 中能够高效的处理并发请求,实现高吞吐率。包括高版本中实行的网络IO异步化。这些都是是实现高性能的重要原因。

 I/O 多路复用模型

在 Linux 中,我们都知道 Linux 对文件的操作实际上就是通过文件描述符(fd),通过一个进程监听多个文件描述符,一旦某个文件描述符准备就绪,就会通知对应的程序响应并处理,这种通知的方式优势在于在单个时间内能够处理更多的链接。

Linux 中的 I/O 多路复用机制是指一个线程处理多个 IO 流,也就是我们通常说的 select/epoll。 在 Redis 单线中,允许在内核中同时存在多个监听文件描述符,内核会去监听在这上面的链接请求,一但有请求就会交给 Redis 线程处理,从而实现一个Redis 线程可以处理多个 IO 流。那么什么是 select、epoll?

1、 select

select 是一个函数,它支持最大的连接数是 1024 或者 2048,因为在 select 函数需要传入fd_set 参数,这个 fd_set 的长度取决于操作系统的位数 1024 或者 2048。

其中 fd_set 是一个 bitmap,当数据没有到缓冲区那么就是 0, 反之到了缓冲区就是 1。select 函数的功能是将 fd_set 遍历,判断标识位是否存在变化,若发生变化就发起中断处理。

2 、epoll

epoll 的首次提出是在 Linux 2.6 内核中,他是为了解决 select 的缺点。

它定义了 epoll_event 结构体来处理,解决 select 存在最大链接数的限制。epoll 不会遍历所有的文件描述符(fd),epoll 会将准备就绪的文件描述符维护在一块指定的空间内,每次从其中取出已经准备就绪的文件描述符进行处理,大大提高了性能。

这就是 select 和 epoll 的区别,想看具体的源码可以自行了解,这里只是简单的描述一下。

3 、Redis I/O 多路复用模型

在 Redis 中,其网络框架调用采用的是复用机制中的 epoll 机制,让内核监听文件描述符,此时 Redis 线程不会阻塞在某一个特定的监听或已连接的文件描述符,从而可以达到同时处理多个链接请求,提高并发性能。如下图,Redis I/O 多路复用模型:

 

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

说说回调机制时如何高效的工作的。当 select/epoll 监测到有文件描述符请求到达时,会发出对应的事件处理,这些事件会被放到一个事件处理队列中,然后 Redis 会对事件进行处理。通过对队列进行轮询,可以提高 CPU 利用率。同时,Redis 在处理事件时,会调用其相应的事件处理函数,实现基于事件的回调。最终使得请求能够第一时间及时响应,再一步提升 Redis 的相应性能。

举个发起读数据的例子,更好的理解上面 Redis I/O 多路复用模型。

当程序发起 Accept 和 Read 事件时, Redis 线程会注册这 Accept 和 Get 事件 对应的回调函数。当 Linux 内核监听到有链接请求或者读数据的请求时,会触发 Accept 和 Read 事件,与此同时调用 Redis 的 Accept 和 Get 函数进行数据处理。

 事件处理流程的更新

Redis 4.0之前的事件处理流程

我们通过IO多路复用器监听来自客户端的socket网络连接,然后由主线程进行IO请求的处理以及命令的处理,所有操作都是线性的

Redis 4.0 之后加入Lazy Free机制

Redis 4.0 之前在处理客户端命令和IO操作时都是以单线程形式运行,期间不会响应其他客户端请求,但若客户端向Redis发送一条耗时较长的命令,比如删除一个含有上百万对象的Set键,或者执行flushdb,flushall操作,Redis服务器需要回收大量的内存空间,这事就会导致Redis服务阻塞,对于负载较高的缓存系统来说将会是个灾难。为了解决这个问题,在Redis 4.0版本引入了Lazy Free,目的是将慢操作异步化,这也是在事件处理上向多线程迈进了一步

Redis 6.0 之后将网络IO异步化

从以上的发展历程中,我们也能看出Redis 的瓶颈并不在CPU上,即使是单线程Redis也能做到很快的响应,除非是遇到个别极其耗时的命令,这一块我们的Redis也在4.0版本做出了优化,但是我们是不是能更进一步优化Redis呢?从上图中我们可以看出主线程不光处理大量的命令,还需要处理大量的网络IO,Redis6.0就是基于此,将IO操作交由其他线程处理

Redis6.0的多线程默认是禁用的,只使用主线程。如需开启需要修改redis.conf配置文件:io-threads-do-reads yes

开启多线程后,还需要设置线程数,否则是不生效的。

线程数一定要小于机器核数。线程数并不是越大越好,官方认为超过了 8 个基本就没什么意义了。

设置线程数,修改redis.conf配置文件: io-threads 6

 

 

 

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

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

相关文章

【ARMv8M Cortex-M33 系列 1 -- SAU 介绍】

文章目录 Cortex-M33 SAU 介绍SAU 的主要功能包括SAU 寄存器配置示例 Cortex-M33 SAU 介绍 在 ARMv8-M 架构中,SAU(Security Attribution Unit)是安全属性单元,用于配置和管理内存区域的安全属性。SAU 是 ARM TrustZone 技术的一…

论文阅读——Flamingo

Flamingo: a Visual Language Model for Few-Shot Learning 模型建模了给定交织的图片或支视频的条件下文本y的最大似然: 1 Visual processing and the Perceiver Resampler Vision Encoder:from pixels to features。 预训练并且冻结的NFNet&#xff…

kindeditor The method toJSONString() is undefined for the type JSONObject

kindeditor 插件上传文件出错的 json_simple-1.1.jar 也不知道是多老的项目,多老的包了,稀有东西

助力智能人群检测计数,基于DETR(DEtectionTRansformer)开发构建通用场景下人群检测计数识别系统

在一些人流量比较大的场合,或者是一些特殊时刻、时段、节假日等特殊时期下,密切关注当前系统所承载的人流量是十分必要的,对于超出系统负荷容量的情况做到及时预警对于管理团队来说是保障人员安全的重要手段,本文的主要目的是想要…

Liteos移植_STM32_HAL库

0 开发环境 STM32CubeMX(HAL库)keil 5正点原子探索者STM32F4ZET6LiteOS-develop分支 1 STM32CubeMX创建工程 如果有自己的工程,直接从LiteOS源码获取开始 关于STM32CubeMX的安装,看我另一篇博客STM32CubeMX安装 工程配置 创建新工程 选择芯片【STM32F…

C++:第九讲前缀和与差分

Everyday English Your optimal career is simply this: Share the real you with physical world through th e process of creative self-expression. 你的最佳职业很简单,就是这样:通过创造性自我表达的途径和世界分享真实的你。 前言 这节课带你们…

Codeforces Round 862 (Div. 2)

Problem - A - Codeforces AC代码: #include<bits/stdc.h> #define endl \n //#define int long long using namespace std; const int N1e310; int a[N]; int n; void solve() {cin>>n;int ans0;for(int i1;i<n;i) cin>>a[i],ans^a[i];if(n%21){for(in…

3.[BUUCTF HCTF 2018]WarmUp1

1.看题目提示分析题目内容 盲猜一波~ &#xff1a; 是关于PHP代码审计的 2.打开链接&#xff0c;分析题目 给你提示了我们访问source.php来看一下 大boss出现&#xff0c;开始详细手撕~ 3.手撕PHP代码&#xff08;代码审计&#xff09; 本人是小白&#xff0c;所以第一步&…

Linux Centos-7.5_64bit 等保测评

一、新增用户 新增test用户 useradd test 设置密码 passwd 修改test的密码 passwd test 修改/etc/sudoers文件&#xff0c;找到下面一行&#xff0c; /etc/sudoers test ALL(ALL) ALL 保存是出现 E45: readonly option is set (add ! to override) 解决办法&#xff…

arduino舵机练习

接地线gnd和电源线5v&#xff1b;信号线链接任意数字针脚 // C code // #include <Servo.h> //引入舵机库Servo servo_2; //定义舵机void setup() {servo_2.attach(2, 500, 2500);/* servo_2.attach(2, 500, 2500) servo_2 对象的一个方法调用&#xff0c;其中包含…

【Amazon 实验①】使用Amazon WAF做基础 Web Service 防护

文章目录 一、实验介绍二、实验环境准备三、验证实验环境四、Web ACLs 配置 & AWS 托管规则4.1 Web ACLs 介绍4.2 Managed Rules 托管规则4.3 防护常见威胁类型&#xff08;sql注入&#xff0c;XSS&#xff09;4.4 实验步骤4.4.1 创建Web ACL4.4.2 测试用例4.4.3 测试结果4…

【Spring实战】配置多数据源

文章目录 1. 配置数据源信息2. 创建第一个数据源3. 创建第二个数据源4. 创建启动类及查询方法5. 启动服务6. 创建表及做数据7. 查询验证8. 详细代码总结 通过上一节的介绍&#xff0c;我们已经知道了如何使用 Spring 进行数据源的配置以及应用。在一些复杂的应用中&#xff0c;…

Linux的/proc/self/学习

文章目录 /proc目录/proc/self的使用 在做SSTI模板注入的CTF题中&#xff0c;发现有师傅提到可以用/proc/self这个目录获取flag&#xff0c;所以也来学习一波主要参考. (我才知道&#x1f601;&#x1f601;&#x1f601;)可以通过/proc/$pid/来获取指定进程的信息&#xff0c…

uniapp uview 页面多个select组件回显处理,默认选中

<view class"add-item column space-around" click"selectClick(1)"><text class"w-s-color-3 f-28">商品分类</text><view class"w-100 space-between"><!-- 第一个参数为你的单选数组&#xff0c;第二个…

Laravel框架使用phpstudy本地安装的composer用Laravel 安装器进行安装搭建

一、首先需要安装Laravel 安装器 composer global require laravel/installer 二、安装器安装好后&#xff0c;可以使用如下命令创建项目 laravel new sys 三、本地运行 php artisan serve 四、 使用Composer快速安装Laravel5.8框架 安装指定版本的最新版本&#xff08;推荐&a…

Kibana下载与安装

Kibana 是一个免费且开放的用户界面&#xff0c;能够让你对 Elasticsearch 数据进行可视化&#xff0c;并 让你在 Elastic Stack 中进行导航。 你可以进行各种操作&#xff0c;从跟踪查询负载&#xff0c;到理解请求如 何流经你的整个应用&#xff0c;都能轻松完成。 下载地址&…

vue3老项目如何引入vite

vue3老项目如何引入vite 安装 npm install vite vitejs/plugin-vue --save-dev Vite官方中文文档修改package.json文件 在 npm scripts 中使用 vite 执行文件 "scripts": {"serve": "vite","build": "vite build","pr…

uniapp使用colorUI

colorUI 微动画 | ColorUI 使用文档 1&#xff1a;把colorui里三个文件复制到自己项目中去 App.vue </script> <style> import url(colorui/icon.css); import url(colorui/main.css); import url("colorui/animation.css");-webkit-keyframes show {…

华清远见嵌入式学习——ARM——作业2

目录 作业要求&#xff1a; 现象&#xff1a; 代码&#xff1a; 思维导图&#xff1a; 模拟面试题&#xff1a; 作业要求&#xff1a; GPIO实验——3颗LED灯的流水灯实现 现象&#xff1a; 代码&#xff1a; .text .global _start _start: 设置GPIOEF时钟使能 0X50000…

opencv视频文件的读写

目录 opencv视频文件的读写 OpenCV调用电脑摄像头 opencv视频文件的读写 在OpenCV中&#xff0c;你可以使用 cv2.VideoCapture 类 来读取视频文件&#xff0c;使用 cv2.VideoWriter 类来写入视频文件。 下面是一个简单的例子&#xff0c;演示如何使用OpenCV读取视频文件、处…