我对Redis线程模型的理解
在网上翻了一下关于"Redis线程模型"搜索结果,都是在说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的整体架构都体现了简单的思想。
- CPU不是瓶颈。在多数的测试下,瓶颈更多的集中在带宽和内存上,如果CPU成为了瓶颈,那么可以使用更多的Redis实例或者集群进行解决。
- 单线程不意味着不可以并发(Concurrent helps)
但是随着Redis后面使用的量越来越大,导致使用单核CPU已经不能满足需求,也需要使用多线程。那么Redis是如何设计多线程呢?
在设计Redis6.0时,原作者antirez
先是思考了多线程的场景,他将多线程分为:
-
并发隔离处理任务(parallelism)
-
慢命令(可以理解为concurrent)两种模式。
在Redis的场景中,他选择使用第二种来作为Redis多线程模式,也与Reactor的线程模式类似。将Redis瓶颈的IO使用多线程实现(主线程仍然是单线程,接受命令,转化IO请求等,从而避免锁),从而增加对CPU的使用能力,提高Redis的处理能力。