06.Redis线程模型常识原理
Redis 使用单线程 Reactor 模型处理命令,主要通过主线程完成客户端请求的接收、解析、数据操作和响应发送。
6.0 版本之前,Redis 仅使用单线程处理所有任务,而 6.0 后引入了多线程来处理 I/O 操作,提升了网络性能。
多线程仅用于网络 I/O,如数据的读取和写入,核心的命令执行仍由单线程完成,确保数据操作的安全性与一致性。
这种改进提高了 Redis 的吞吐能力,特别适合高并发场景。
# 01.Redis 线程模型
# 1、线程模型概述
Redis 底层是 Reactor模型,Reactor模型有三种
- 单线程Reactor模型
- 多线程Reactor模型
- 主从Reactor模型
Redis 单线程理解
Redis单线程主要指Redis-server主线程,不是说Redis生命周期只有一个线程
Redis单线程,指的是命令处理、逻辑处理在一个单线程中
接收客户端请求
-->解析请求
-->进行数据读写等操作
-->发送数据给客户端
是主线程完成而是其主线程(即下图的
任务队列
以及事件分派器
)为单线程
# 2、6.0前单线模式
1)建立连接
(连接事件
)1、建立连接
- 客户端尝发送TCP连接请求,连接请求被
操作系统内核
接收并放入等待队列
IO多路复用器
监控等待队列,发现新连接请求,将其放入事件队列
,等待被处理
- 客户端尝发送TCP连接请求,连接请求被
2、文件分派器
文件分派器
将会从事件队列中取出这个新的连接请求,将其分配给连接应答器
(acceptor)处理
3、连接应答器
连接应答器
的任务是接受新的连接请求,建立新的socket连接
- 连接应答器将新的socket放入IO多路复用器监控的文件描述符集合,并向IO多路复用器发送一个读就绪信号
2)处理客户端请求
(读事件
)- 客户端发送请求到Redis服务器时,请求被
IO多路复用器
标记为读事件
- IO多路复用器接收到读事件后,会将其
放入事件队列中
Redis主线程
会从事件队列中取出读事件
,然后调用相应的事件处理器来处理- 读事件处理器将请求数据
解析成Redis命令和参数
,根据命令类型调用相应的命令处理函数来处理 - 命令处理完毕后,
Redis会生成一条回复消息
,并将其标记为一个写事件,等待被发送回客户端
- 客户端发送请求到Redis服务器时,请求被
3)数据发送给客户端
(写事件
)- 当有数据需要
发送回客户端时
,这个发送操作
会被标记为一个写事件
- IO多路复用器会将写事件放入事件队列中
主线程
会从事件队列中取出写事件,调用相应的事件处理器来处理这个事件- 对于写事件,Redis会调用写事件处理器,
将回复消息写入到socket
,然后发送给客户端
- 当有数据需要
注1:
- 读事件和写事件都是异步处理的,不会因为一个读事件或写事件阻塞住
- 而是会将事件放入事件队列,然后继续处理其他的事件
注2:
下图“写发送队列”指的是返回数据给客户端,这个过程需要写入到 socket
# 3、6.0为什么引入IO多线程
# 1、引入原因
在
Redis 6.0 版本之后
,也采用了多个 I/O 线程
来处理网络请求因为随着网络硬件的性能提升,Redis的性能瓶颈有时会出现在网络 I/O 的处理上
所以为了提高网络 I/O 的并行度,Redis 6.0
对于网络 I/O
采用多线程来处理但是
对于命令的执行
,Redis 仍然使用单线程来处理
即
多线程处理网络IO
(``read、decode和
encode、send`阶段)主线程使用单线程,执行命令处理业务逻辑
# 2、引入后工作流程
主线程:执行命令,将结果写入队列
工作线程:读取请求数据、从队列中读取数据到 socket、关闭 socket 等
原因:Redis 的数据结构和操作都不是线程安全的,如果同时有多个线程对数据进行读写,可能会导致数据的不一致
- 6.0 后依然需要
一个主线程
,可以有多个工作线程
处理用户 I/O - 1)工作线程接收到客户端请求,从 socket 中读取请求数据
- 2)主线程解析出请求命令和参数,执行请求命令,获取或修改数据,然后生成响应数据
- 3)主线程将响应数据写入一个中间队列,然后唤醒工作线程
- 4)工作线程从中间队列中取出响应数据,然后将数据写入 socket,发送给客户端