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 多路复用模型:

相关推荐
希忘auto1 小时前
详解Redis之事务
redis
yours_Gabriel1 小时前
【Redis_1】初识Redis
数据库·redis·缓存
萝卜青今天也要开心2 小时前
读书笔记-《Redis设计与实现》(二)单机数据库实现(上)
java·数据库·redis·学习·缓存
liuhaikang3 小时前
鸿蒙HarmonyOS Next 视频边播放边缓存- OhosVideoCache
缓存·音视频·harmonyos
biubiubiu07064 小时前
Redis缓存穿透,雪崩,击穿
数据库·redis·缓存
lingllllove8 小时前
ubuntu22.04防火墙策略
数据库·postgresql
程序猿小D11 小时前
第三百五十八节 JavaFX教程 - JavaFX滑块
java·前端·数据库
memorycx11 小时前
MySQL(3)
数据库·sql
My LQS11 小时前
使用 EXISTS 解决 SQL 中 IN 查询数量过多的问题
数据库·sql