目录
Redis到底是单线程还是多线程?
1.对于读写命令来说,Redis一直是单线程。
[接收客户端请求->解析请求->数据读写等操作->返回结果给客户端],这个过程是由一个主线程完成的,所以我们常说 Redis 是单线程的。
而且 Redis 基于单线程事件驱动模型,内部使用的文件事件处理器是单线程的,所以决定了 Redis 也是单线程的。
2.Redis4.0 之后引入了多线程来处理任务,比如清理脏数据、AOF重写、生成RDB快照。
3.Redis6.0 之后引入了多线程来处理IO请求,提高网络IO的读写性能。
多线程模型只是用来处理【网络数据的读写】和【协议解析】的,执行读写操作依然是单线程。
6.0之前为什么使用单线程?
Redis 是基于内存的,读写速度非常快,CPU 不是 Redis 的瓶颈,使用单线程编程更简单更容易维护;
相反,如果引入多线程后,可能会存在死锁、线程上下文切换、加锁解锁这些操作,还会带来额外的开销。
6.0之后为什么使用多线程?
Redis 的瓶颈不是CPU,而是内存和网络IO
- 如果内存不够的话,可以加内存或者左数据结构的优化
- 但是网络IO的性能才是更重要的,因为网络IO读写在Redis整个执行期间占据了大部分时间,所以Redis在6.0版本引入了多线程来处理网络请求,提高网络IO的读写性能
Redis的单线程模型
Redis基于Reactor模式设计开发了一套高效的事件处理模型——文件事件处理器
这个文件事件处理器是单线程的,所以决定了 Redis 是单线程
文件事件处理器的结构包含5个部分:
- 多个socket:是网络通信的起点,Redis 为每个连接的客户端维护了一个 socket,用来接收请求和发送响应
- IO多路复用程序:是文件事件处理器的核心,它会监听所有的 socket 并判断哪一个 socket 已经做好进行读写操作的准备了。然后把产生的事件放到任务队列中排队。
- 任务队列:处理任务
- 文件事件分派器:每次从任务队列中取出一条任务,根据事件的类型转发给对应的事件处理器
- 事件处理器:负责处理事件
Redis的IO多线程模型
之前提到过,Redis6.0之后,引入多线程来处理网络IO请求,提高读写性能
所以,一条命令被拆分成两个部分来执行:
—【网络数据的读写】和【请求解析】使用多线程来处理
—执行请求的读写操作,还是使用主线程,单线程处理
流程:
- 主线程负责接收、建立多个连接请求,获取 socket 之后,放入全局等待处理队列
- 主线程通过轮询,将可读的 socket 分配给IO线程
- IO线程开始读取并解析 socket,此时主线程会阻塞,等待IO线程处理完成
- IO线程解析完毕之后,主线程会执行解析出来的 Redis 命令,把结果写入输出缓冲区
- 然后IO线程将结果写回 socket ,此时主线程阻塞,等待IO线程处理完毕
- socket 写回完成后,主线程执行所有的命令,并清空整个等待队列。然后再等待后续的请求,重复下一波,循环往复......