为什么单线程Redis能那么快? 一方面,Redis 的大部分操作在内存上完成,再加上它采用了高效的数据结构,例如哈希表和跳表,这是它实现高性能的一个重要原因。另一方面,就是 Redis 采用了多路复用机制,使其在网络 IO 操作中能并发处理大量的客户端请求,实现高吞吐率。接下来,我们就重点学习下多路复用机制。

Redis 是单线程,主要是指 Redis 的网络 IO 和键值对读写是由一个线程来完成的,这也是 Redis 对外提供键值存储服务的主要流程。但 Redis 的其他功能,比如持久化、异步删除、集群数据同步等,其实是由额外的线程执行的。所以,严格来说,Redis 并不是单线程,但是我们一般把 Redis 称为单线程高性能。

  • 大部分操作内存完成,高效的数据结构
  • 多路复用机制,网络 IO 操作中能并发处理大量的客户端请求,实现高吞吐率

基本IO模型

Redis高性能原理:源码上解析redis单线程/reactor 网络模型_单线程

在这里的网络 IO 操作中,有潜在的阻塞点,分别是 accept() 和 recv()。当 Redis 监听到一个客户端有连接请求,但一直未能成功建立起连接时,会阻塞在 accept() 函数这里,导致其他客户端无法和 Redis 建立连接。类似的,当 Redis 通过 recv() 从一个客户端读取数据时,如果数据一直没有到达,Redis 也会一直阻塞在 recv()。

socket 网络模型本身支持非阻塞模式,在 socket 模型中,不同操作调用后会返回不同的套接字类型。

Redis高性能原理:源码上解析redis单线程/reactor 网络模型_单线程_02

基于多路复用的高性能 I/O 模型

指一个线程处理多个 IO流,常听说的select/epoll 机制。简单来说,在 Redis 只运行单线程的情况下,该机制允许内核中,同时存在多个监听套接字和已连接套接字。内核会一直监听这些套接字上的连接请求或数据请求。一旦有请求到达,就会交给 Redis 线程处理,这就实现了一个 Redis 线程处理多个 IO 流的效果。Redis 线程不会阻塞在某一个特定的监听或已连接套接字上,也就是说,不会阻塞在某一个特定的客户端请求处理上。正因为此,Redis 可以同时和多个客户端连接并处理请求,从而提升并发性。

Redis高性能原理:源码上解析redis单线程/reactor 网络模型_网络_03