Redis真的是单线程的吗?

在学习redis的过程中老是听到:Redis快的原因之一是单线程模型,省去线程切换和竞争的性能开销,但是深入了解redis之后发现它并不是纯的单线程。

Redis 单线程指的是「接收客户端请求->解析请求 ->进行数据读写等操作->发送数据给客户端」这个过程是由一个线程(主线程)来完成的,这也是我们常说 Redis 是单线程的原因。

但是,Redis 程序并不是单线程的,Redis 在启动的时候,是会启动后台线程(BIO)的:

Redis 在 2.6 版本,会启动2个后台线程,分别处理关闭文件、AOF 刷盘这两个任务;.·Redis 在 4.0 版本之后,新增了一个新的后台线程,用来异步释放 Redis 内存,也就是 lazyfree 线程例如执行 unlink key/flushdb async/flushall async 等命令,会把这些删除操作交给后台线程来执行好处是不会导致 Redis 主线程卡顿。因此,当我们要删除一个大 key 的时候,不要使用 del 命令删除因为 del 是在主线程处理的,这样会导致 Redis 主线程卡顿,因此我们应该使用 unlink 命令来异步删除大key。

之所以 Redis 为「关闭文件、AOF 刷盘、释放内存」这些任务创建单独的线程来处理,是因为这些任务的操作都是很耗时的,如果把这些任务都放在主线程来处理,那么 Redis 主线程就很容易发生阻塞,这样就无法处理后续的请求了。

后台线程相当于一个消费者,生产者把耗时任务丢到任务队列中,消费者(BIO)不停轮询这个队列,拿出任务就去执行对应的方法即可。

虽然 Redis 的主要工作(网络 /O 和执行命令)-直是单线程模型,但是在 Redis 6.0 版本之后,也采用了多个 I/0 线程来处理网络请求,这是因为随着网络硬件的性能提升,Redis的性能瓶颈有时会出现在网络 //0 的处理上.

所以为了提高网络 I/0 的并行度,Redis 6.0 对于网络 I/0 采用多线程来处理。但是对于命令的执行Redis 仍然使用单线程来处理,所以大家不要误解Redis 有多线程同时执行命令。

Redis 官方表示,Redis 6.0 版本引入的多线程 I/0 特性对性能提升至少是一倍以上

Redis 6.0 版本支持的 I/0 多线程特性,默认情况下 1/0 多线程只针对发送响应数据(write client socket),并不会以多线程的方式处理读请求(read cient socket)。要想开启多线程处理客户端读请求,就需要把 Redis.conf 配置文件中的 io-threads-do-reads 配置项设为 yes。

复制代码
//读请求也使用io多线程
io-threads-do-reads yes

同时,Redis.conf 配置文件中提供了 10 多线程个数的配置项。

// io-threads N,表示启用 N-1 个 I/0 多线程(主线程也算一个 I/0 线程)io-threads 4

关于线程数的设置,官方的建议是如果为 4核的 CPU,建议线程数设置为 2 或 3,如果为8核 CPU 建议线程数设置为 6,线程数一定要小于机器核数,线程数并不是越大越好。

因此, Redis 6.0 版本之后,Redis 在启动的时候,默认情况下会额外创建6个线程(这里的线程数不包括主线程)

Redis-server: Redis的主线程,主要负责执行命令

bio_close_file、bio_aof_fsync、bio_lazy_free:三个后台线程,分别异步处理关闭文件任务、AOF刷盘任务、释放内存任务;

io thd 1、io_thd 2、io_ thd 3:三个1/0 线程,io-threads默认是4,所以会启动3(4-1)个//0多线程,用来分担 Redis 网络 //0 的压力。

为什么 Redis 中要使用 /0 多路复用这种技术呢?

因为 Redis 是跑在「单线程」中的,所有的操作都是按照顺序线性执行的,但是由于读写操作等待用户输入 或 输出都是阻塞的,所以I/O 操作在一般情况下往往不能直接返回,这会导致某一文件的 I/O阻塞导,致整个进程无法对其它客户提供服务。而 I/O 多路复用就是为了解决这个问题而出现的。为了让单线程(进程)的服务端应用同时处理多个客户端的事件,Redis 采用了 I/O多路复用机制。

这里"多路"指的是多个网络连接客户端,"复用"指的是复用同一个线程(单进程)。I/O多路复用其实是使用一个线程来检査多个 Socket 的就绪状态,在单个线程中通过记录跟踪每一个 socket(1/0流)的状态来管理处理多个I /O 流。如下图是 Redis 的I /O 多路复用模型:

相关推荐
梁bk3 分钟前
Redis 持久化机制:RDB 和 AOF
redis
S***y3969 分钟前
MySQL视频
数据库·mysql
CS_浮鱼31 分钟前
【Linux进阶】mmap实战:文件映射、进程通信与LRU缓存
linux·运维·c++·缓存
周杰伦fans37 分钟前
[特殊字符] 代理模式超详细讲解 ——.NET
数据库·c#·代理模式
TDengine (老段)1 小时前
TDengine 转换函数 TO_JSON 用户手册
android·大数据·数据库·json·时序数据库·tdengine·涛思数据
2301_800256111 小时前
第七章 空间存储与索引 知识点梳理3(空间填充曲线)
数据库·笔记·sql·postgresql
冰封剑心1 小时前
MiniCPM-V-2_6 (4-bit 量化)使用
java·前端·数据库
小满、2 小时前
MySQL :存储引擎原理、索引结构与执行计划
数据库·mysql·索引·mysql 存储引擎
x***13392 小时前
SQL Server 创建用户并授权
数据库·oracle
JIngJaneIL2 小时前
智慧物业|物业管理|基于SprinBoot+vue的智慧物业管理系统(源码+数据库+文档)
java·前端·数据库·vue.js·spring boot·论文·智慧物业管理系统