聊 Redis 线程模型之前,先思考一个问题:Redis 是单线程的,但为什么可以支持高并发?
这问题的答案我认为可以从以下几个点回答:
1.纯内存操作——内存操作肯定比普通的操作快呀!
2.非阻塞 IO 多路复用程序—— Redis 核心
3.单线程避免上下文切换带来的CPU消耗
其中第二点,Redis 核心是非阻塞 IO 多路复用程序,这是什么东东?
那就要引入这篇文章的主角———— Redis 线程模型
简介:
Redis 线程模型实际上是 Redis 基于 Reactor 模式开发的文件事件处理器(File Event Handler)。简单来说,文件事件处理器可以监听多个客户端的 socket,并根据 socket 产生的事件选择不同的事件处理器处理客户端连接请求、命令请求和响应请求。
文件事件处理器的组成:
多个 Socket: Redis 服务器会为每个发起连接 Redis 的客户端创建对应的 Socket
IO 多路复用程序: 可以同时监听多个 socket,当 Socket 产生事件,IO多路复用程序会将 Socket 塞进队列。
文件事件分派器: 接收队列的 Socket 并分派到 Socket 事件关联的事件处理器。
事件处理器: 包括连接应答处理器、命令请求处理器、命令回复处理器、复制处理器。
连接应答处理器:对连接服务器的客户端进行应答。
命令请求处理器:接收客户端发过来的请求。
命令回复处理器:向客户端返回命令的执行结果。
复制处理器:当从服务器向主服务器进行复制的操作时,主从服务器都需要关联复制处理器。
文件事件处理器可以接收多个客户端的发过来的请求信息,请求信息会产生相应的事件(譬如:AE_READABLE
、AE_WRITEABLE
),然后非阻塞 IO 多路复用程序监听到 socket 产生的事件就会把 socket 塞进队列,再通过文件事件分派器选择事件对应的处理器处理。
通过上面的简单介绍文件事件处理器,再回顾“ Redis 是单线程的,但为什么可以支持高并发?”的答案,相信你会有不一样的感受!
什么?!还是不太明白 Redis 为什么效率那么高?文件事件处理器的各个组成也不太清楚有什么联系?接下来我通过画图,一步一图的方式尽可能的理清 Redis 线程模型的样貌。
模拟客户端和 Redis 服务器的通信过程
1.在 Redis 服务器初始化的时候,Redis 服务器的 Server Socket 会产生 AE_READABLE 事件并且会与连接应答处理器
关联;接下来,IO 多路复用程序监听到 server socket 产生了事件就会将 socket 塞进队列,然后通过文件事件分派器交给连接应答处理器
处理。
2.当客户端 A 发起连接 Redis 服务器的时候,实际上是客户端 A 的 socket 与 Redis 服务器的 Server socket 连接,此时 Redis 服务器的连接应答处理器
会执行相应客户端 A socket 的应答操作,它会创建一个与客户端 A 连接的 Client A socket ;
当客户端 A 向 Redis 服务器发起请求,实际上是客户端 A Socket 与 Redis 服务器的 Client A Socket 通信,此时 Client A Socket 会产生AE_READABLE
事件并且与命令请求处理器
关联,然后 IO 多路复用程序监听到客户端 Client A Socket 产生了事件,照旧会塞进队列,再由文件事件分配器交给命令请求处理器
接收客户端的请求。
3.当命令请求处理器
处理完 Client A Socket 的命令,Client A Socket 会产生AE_WRITEABLE
事件并且与命令回复处理器
关联,此时 IO 多路复用程序监听到 Client A Socket 产生事件后,再次将 Client A Socket 塞进队列,由文件事件分派器交给命令回复处理器
执行,命令回复处理器
会将命令的回复写入 Client A Socket 后由客户端 A 读取,并且解除 Client A Socket 与命令回复处理器
的关联。
总结:
以上就是客户端与 Redis 服务器通信的过程。如果是多个客户端并发向 Redis 服务器发送请求怎么办?其实是相似的,当多个客户端连接 Redis 服务器,连接应答处理器
都会创建与客户端通信的 Socket ;在 Redis 服务器内有多个 Socket 怎么办?由于 IO 多路复用程序是非阻塞的,所以会快速的将监听到的 Socket 塞进队列并且由文件事件分派器交给指定的处理器处理。最主要的是,这一系列的过程都是基于内存的单线程操作,由产生 Socket 到被处理器处理整个过程可能都没有几微秒,所以 Redis 才能做到理论上 10+万的QPS。(Redis QPS 受实际机器等环境影响)
参考资料:
《Redis 设计与实现》
中华石杉老师的课程 ——《Java工程师面试突击第一季》