在网上翻了一下关于"Redis线程模型"搜索结果,都是在说IO多路复用。但是完整的线程模型应该更整体的,而不仅仅是IO处理模式,所以决定把自己的思考记录下来。
Redis线程分类
总结地看一下Redis中的线程,一共有三类线程:
- socker连接线程-套接字
- Redis主线程
- 后台线程(处理BGSAVE命令等操作)
因为Redis是类似单线程,所以线程模型很简单。在简单的线程下,Redis线程是如何工作的呢?
根据上面线程的划分,主要分成下面两个部分:
Redis处理请求方式
- socket线程连接用来连接客户端,并写入新事件到文件描述符中
- 主线程通过多路复用(multiplexing)抽象API读取请求
- 通过reactor的handler模式实现响应请求
Redis后台线程工作方式
- 从主进程中fork出子线程,利用linux的
copy-on-write
技术节省内存 - 在子线程处理完成后,通知主线程
讲完了Redis的线程模型,接下来我们来看一下,为什么Redis要设计成单线程的,以及Redis 6.0之后的"多线程"?
Redis为什么单线程及演进的变化
为什么Redis要设计成单线程的呢?
- 首先,简单是第一考虑因素,在Redis的整体架构都体现了简单的思想。
- CPU不是瓶颈。在多数的测试下,瓶颈更多的集中在带宽和内存上,如果CPU成为了瓶颈,那么可以使用更多的Redis实例或者集群进行解决。
- 单线程不意味着不可以并发(Concurrent helps)
但是随着Redis后面使用的量越来越大,导致使用单核CPU已经不能满足需求,也需要使用多线程。那么Redis是如何设计多线程呢?
在设计Redis6.0时,原作者antirez
先是思考了多线程的场景,他将多线程分为以下两个模式:
- 并行处理任务(parallelism)
- 慢命令(一个命令慢,导致其他的命令也慢,可以理解为concurrent)
在Redis的场景中,他选择使用第二种来作为Redis多线程模式,也与Reactor的线程模式类似。将Redis瓶颈的IO使用多线程实现(主线程仍然是单线程,接受命令,转化IO请求等,从而避免锁),从而增加对CPU的使用能力,提高Redis的处理能力。