Redis 到底是单线程还是多线程呢?

news2025/7/12 22:29:18

前言

Redis是高性能分布式缓存常用中间件,我们经常说Redis是单线程的,
也有人说Redis在6.0版本采用了多线程,那么Redis到底是采用单线程呢?还是多线程?

通常说 Redis 是单线程,其实主要是指 Redis 对外提供键值存储服务的主要流程,
即网络 IO 和键值存储服务是由⼀个线程来完成的。

除此之外外的其他功能, 如持久化、 缓存过期、集群同步等,是由额外的线程执⾏的。
防止有同步阻塞,导致主线程被占用影响后续的逻辑执行。

Redis 为什么用单线程

Redis 单线程到底指什么?

大家所熟知的 Redis 确实是单线程模型,
指的是执行 Redis 命令的核心模块是单线程的,
而不是整个 Redis 实例就一个线程,Redis 其他模块还有各自模块的线程。

参见下图:

  • aeApiPoll:事件分派,I/O 多路复用 API,是基于 epoll_wait/select/kevent 等系统调用的封装,监听等待读写事件触发,然后处理,它是事件循环(Event Loop)中的核心函数,是事件驱动得以运行的基础。
  • acceptTcpHandler:连接应答处理器,底层使用系统调用 accept 接受来自客户端的新连接,并为新连接注册绑定命令读取处理器,以备后续处理新的客户端 TCP 连接;除了这个处理器,还有对应的 acceptUnixHandler 负责处理 Unix Domain Socket 以及 acceptTLSHandler 负责处理 TLS 加密连接。
  • readQueryFromClient:命令读取处理器,解析并执行客户端的请求命令。
  • sendReplyToClient:命令回复处理器,当一次事件循环之后写出缓冲区中还有数据残留,则这个处理器会被注册绑定到相应的连接上,等连接触发写就绪事件时,它会将写出缓冲区剩余的数据回写到客户端。

Redis基于Reactor模式开发了网络事件处理器,这个处理器被称为文件事件处理器 。
它的组成结构为4部分:多个套接字、IO多路复用程序、文件事件分派器、事件处理器。
因为文件事件分派器队列的消费是单线程的,所以Redis才叫单线程模型。

优点

  • Redis是基于内存的操作,磁盘IO以及CPU不是Redis的瓶颈,
    Redis的瓶颈最有可能是机器内存的大小和网络带宽。
  • 采用单线程,避免了不必要的上下文切换和竞争条件,
    也不存在多进程或者多线程导致的切换而消耗 CPU。
  • 不用去考虑各种锁的问题,不存在加锁释放锁操作,
    没有因为可能出现死锁而导致的性能消耗

Redis6.0 多线程

Redis 6.0
Redis 6.0 (GA October, 2021) introduced SSL, the new RESP3 protocol, ACLs, client side caching, diskless replicas, I/O threads, faster RDB loading, new modules APIs, and many more improvements.
See the release notes or download 6.0.16.

I/O threads 说的就是多线程。

多线程引入原因

多线程是 Redis6.0 推出的一个新特性。Redis 是核心线程负责网络 IO ,
命令处理以及写数据到缓冲, 而随着网络硬件的性能提升,
单个主线程处理⽹络请求的速度跟不上底层⽹络硬件的速度,
导致网络 IO 的处理成为了 Redis 的性能瓶颈。

而 Redis6.0 就是从单线程处理网络请求到多线程处理,
通过多个 IO 线程并⾏处理网络操作提升实例的整体处理性能。
需要注意的是对于读写命令,Redis 仍然使⽤单线程来处理,
这是因为继续使⽤单线程执行命令操作,就不⽤为了保证 Lua 脚本、事务的原⼦性,
额外开发多线程互斥机制了。

需要注意的是在 Redis6.0 中,多线程机制默认是关闭的,需要在 redis.conf 中
完成以下两个设置才能启用多线程。

设置 io-thread-do-reads 配置项为 yes,表示启用多线程。
io-threads-do-reads yes
设置线程个数。⼀般来说,线程个数要小于 Redis 实例所在机器的 CPU 核数,
例如,对于⼀个 8 核的机器来说,Redis 官⽅建议配置 6 个 IO 线程。
io-threads 6

多线程流程

全部流程主要分为 4 个阶段:

阶段一:服务端和客⼾端建立 Socket 连接,并分配处理线程

当有客⼾端请求和实例建立 Socket 连接时,主线程会创建和客户端的连接,
并把 Socket 放入全局等待队列中。然后主线程通过轮询方法把 Socket 连接
分配给 IO 线程。

阶段二:IO 线程读取并解析请求

主线程把 Socket 分配给 IO 线程后,会进⼊阻塞状态等待 IO 线程
完成客户端请求读取和解析。

阶段三:主线程执⾏请求操作

IO 线程解析完请求后,主线程以单线程的⽅式执⾏这些命令操作。

阶段四:IO 线程回写 Socket 和主线程清空全局队

主线程执行完请求操作后,会把需要返回的结果写入缓冲区。
然后,主线程会阻塞等待 IO 线程把这些结果回写到 Socket 中,
并返回给客户端。等到 IO 线程回写 Socket 完毕,主线程会清空全局队列,
等待客户端的后续请求。

小结

随着线上服务流量越来越大,Redis 的单线程模式会导致系统消耗很多 CPU 时间
在网络 I/O 上从而降低吞吐量,要提升 Redis 的性能有两个方向:

  • 优化网络 I/O 模块
  • 提高机器内存读写的速度

后者依赖于硬件的发展,暂时无解。所以只能从前者下手,网络 I/O 的优化又可以分为两个方向:

  • 零拷贝技术或者 DPDK 技术
  • 利用多核优势

模型缺陷

Redis 的多线程网络模型实际上并不是一个标准的 Multi-Reactors/Master-Workers 模型,
和其他主流的开源网络服务器的模式有所区别,
最大的不同就是在标准的 Multi-Reactors/Master-Workers 模式下,
Sub Reactors/Workers 会完成 网络读 -> 数据解析 -> 命令执行 -> 网络写 整套流程,Main Reactor/Master 只负责分派任务,
而在 Redis 的多线程方案中,I/O 线程任务仅仅是通过 socket 读取客户端请求命令并解析,却没有真正去执行命令,所有客户端命令最后还需要回到主线程去执行,因此对多核的利用率并不算高,而且每次主线程都必须在分配完任务之后忙轮询等待所有 I/O 线程完成任务之后才能继续执行其他逻辑。

Redis 之所以如此设计它的多线程网络模型,我认为主要的原因是为了保持兼容性,因为以前 Redis 是单线程的,所有的客户端命令都是在单线程的事件循环里执行的,也因此 Redis 里所有的数据结构都是非线程安全的,现在引入多线程,如果按照标准的 Multi-Reactors/Master-Workers 模式来实现,则所有内置的数据结构都必须重构成线程安全的,这个工作量无疑是巨大且麻烦的。

参考文章

https://blog.csdn.net/weixin_41605937/article/details/111982403
https://segmentfault.com/a/1190000041275783

更多技术文章,请关注公众号『码农札记』!!

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

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

相关文章

CNCF基金会成员的分类

CNCF简介 2015年,谷歌与Linux基金会及众多行业合作伙伴一起建立了一个云原生计算基金会(CNCF,Cloud Native Computing Foundation)。CNCF旨在创建并推动一个新的计算范式,这个范式的目的是增强现代分布式系统&#xf…

dataset.py篇

dataset.py 目录: 前言观察数据书写代码函数解释 前言 在步骤中需要写自己的dataset类,并将label和image一一对应后返回。 观察数据 在书写dataset前最重要的就是要观察数据集,对数据集进行分析,比如了解图片大小&#xff0c…

maven基础入门

maven 1、maven简介 Apache Maven 是一个项目管理和构建工具,它基于项目对象模型(POM)的概念,通过一小段描述信息来管理项目的构建、报告和文档。官网 :http://maven.apache.org/什么是Maven?这里先引用知乎的一个回答 我先不说…

第五届“传智杯”全国大学生计算机大赛(练习赛) [传智杯 #5 练习赛] 复读

[传智杯 #5 练习赛] 复读 题目描述 给定若干个字符串,不定数量,每行一个。有些字符串可能出现了多次。如果读入一个字符串后,发现这个字符串以前被读入过,则这个字符串被称为前面相同的字符串的复读,这个字符串被称为…

Redis分布式锁剖析和几种客户端的实现

1. 背景 在传统的单体项目中,即部署到单个IIS上,针对并发问题,比如进销存中的出库和入库问题,多个人同时操作,属于一个IIS进程中多个线程并发操作的问题,这个时候可以引入线程锁lock/Monitor等,…

信息论随笔(三)交互信息量

之前讨论了一个事件的自信息量,但是实际情况下往往有多个事件发生,而且这些事件之间相互是有联系的。比如知道一个人踢足球,那么这个人很有可能会看世界杯。也就是说,我们可以通过一个事件获得另外一个事件的信息,或者…

解决Android Studio等开发软件出现更新TKK失败的两种方案

解决Android Studio等开发软件出现更新TKK失败的两种方案方案一 配置hosts1. 配置域名与IP2.扫描国内可用的IP方案二 替换翻译引擎百度翻译引擎在Android Studio等开发软件中利用Translation等翻译插件时,出现无法翻译的提示:更新TKK失败,请检…

数据结构之栈的实现及相关OJ题

🕺作者启明星使 🎃专栏:《数据库》《C语言》 🏇分享一句话: 对的人会站在你的前途里 志同道合的人才看得懂同一片风景 大家一起加油🏄‍♂️🏄‍♂️🏄‍♂️ 希望得到大家的支持&am…

【毕业设计】新闻分类系统 - 深度学习 机器学习

文章目录0 前言1 简介2 参与及比较算法3 先说结论4 实现过程4.1 数据爬取4.2 数据预处理5 CNN文本分类6 最后0 前言 🔥 Hi,大家好,这里是丹成学长的毕设系列文章! 🔥 对毕设有任何疑问都可以问学长哦! 这两年开始&a…

事件总线EventBus

事件总线是对发布-订阅模式的一种实现,是一种集中式事件处理机制,允许不同的组件之间进行彼此通信而又不需要相互依赖,达到一种解耦的目的。 什么是“总线”:一个集中式的事件处理机制。同时服务多个事件和多个观察者。相当于一个…

C#编程深入研究变量,类型和方法

编写正确的C#代码 简单的调试技术 变量的语法 声明类型和值 仅声明类型 访问修饰符 使用类型 通用内置类型 类型转换 推断式声明 自定义类型 类型综述 命名变量 变量的作用域 运算符 定义方法 指定参数 指定返回值 常见的Unity方法 Start方法 Update方法 …

金山云:基于 JuiceFS 的 Elasticsearch 温冷热数据管理实践

01 Elasticsearch 广泛使用带来的成本问题 Elasticsearch(下文简称“ES”)是一个分布式的搜索引擎,还可作为分布式数据库来使用,常用于日志处理、分析和搜索等场景;在运维排障层面,ES 组成的 ELK&#xff…

MMDetection3D库中的一些模块介绍

本文目前仅包含2个体素编码器、2个中间编码器、1个主干网络、1个颈部网络和1个检测头。如果有机会,会继续补充更多模型。 若发现内容有误,欢迎指出。 MMDetection3D的点云数据一般会经历如下步骤/模块: #mermaid-svg-q9Wy2NQvFHfuPWKs {font-…

骨传导原理是什么,佩戴骨传导耳机的过程中对于耳道有无损害

随着新时代的到来,我们周围的数码产品逐渐被新产物所替代,以往在耳机市面上,普遍都是入耳式耳机,但长时间佩戴这种耳机的话对于我们耳道来说是有着不可逆的伤害,而在近几年骨传导耳机的出现,打破了传统耳机…

18.Redis系列之AOF方式持久化

本文学习redis7两大持久化技术之一:AOF(Append Only File)日志追加方式持久化备份与还原,重写以及AOF方式的优缺点 1. AOF相关配置 首先我们先简单了解下Redis7中AOF相关配置 // 开启AOF方式持久化,默认no appendon…

基于真实场景解读 K8s Pod 的各种异常

在 K8s 中,Pod 作为工作负载的运行载体,是最为核心的一个资源对象。Pod 具有复杂的生命周期,在其生命周期的每一个阶段,可能发生多种不同的异常情况。K8s 作为一个复杂系统,异常诊断往往要求强大的知识和经验储备。结合…

骚戴独家笔试---SQL笔试

SQL笔试训练 查询结果去重 两种答案 查找某个年龄段的用户信息 查找除复旦大学的用户信息 三种答案 用where过滤空值练习 三种答案 查询NULL时&#xff0c;不能使用比较运算符(或者< >)&#xff0c;需要使用IS NULL运算符或者IS NOT NULL运算符。 操作符混合运用 我这里…

力扣 792. 匹配子序列的单词数

题目 给定字符串 s 和字符串数组 words, 返回 words[i] 中是s的子序列的单词个数 。 字符串的 子序列 是从原始字符串中生成的新字符串&#xff0c;可以从中删去一些字符(可以是none)&#xff0c;而不改变其余字符的相对顺序。 例如&#xff0c; “ace” 是 “abcde” 的子序…

java spring引用外部jar包并使用

spring引用外部jar包并使用1、将jar包放到src/main/resources/lib2、编辑pom.xml文件build下面加入resources&#xff0c;不加话的打包会找不到资源3、project structure中引入该lib1、将jar包放到src/main/resources/lib 2、编辑pom.xml文件 打开pom文件&#xff0c;找到相应…

计算机网络基本知识

计算机网络基本知识 计算机网络定义&#xff1a;是一个将分散的、具有独立功能的计算机系统&#xff0c;通过通信设备与线路连接起来&#xff0c;由功能完善的软件实现资源共享和信息传递的系统。 1.1计算机网络在信息时代作用 1.2因特网概述 1.2.1网络、互联网、因特网 网…