Skip to content

Redis单线程高性能 + IO多路复用

一、Redis单线程速度快的核心原因

  1. 纯内存操作 数据全部驻留内存,避开低速磁盘IO,内存读写为纳秒级,性能瓶颈主要在网络传输。

  2. 单线程架构 无需处理多线程上下文切换、锁竞争与线程安全问题,CPU资源全部用于业务数据处理。

  3. IO多路复用(epoll)非阻塞网络模型 单线程可同时监听大量客户端Socket,无空闲轮询空转,高效支撑海量并发连接。

二、Linux用户空间&内核空间

  1. 用户空间(Ring3):应用程序运行区域,无硬件操作权限,不能直接操作网卡、磁盘等硬件。
  2. 内核空间(Ring0):操作系统内核区域,拥有硬件操作特权,统一管理各类硬件设备。
  3. IO数据流转规则 读数据:硬件 → 内核缓冲区 → 用户缓冲区 写数据:用户缓冲区 → 内核缓冲区 → 硬件 所有IO操作都必须经过内核中转。

三、Linux四种IO模型对比

1. 阻塞IO Blocking IO

两个阶段全程阻塞: ① 等待数据到达内核缓冲区,进程挂起等待网络数据; ② 内核将数据拷贝至用户空间,进程继续阻塞。 缺点:单线程仅能处理一个连接,并发能力极低。

2. 非阻塞IO Non-Blocking IO

阶段一:无数据则直接返回错误码,进程持续轮询请求数据,造成CPU空转浪费; 阶段二:数据就绪后,内核拷贝数据阶段进程依旧阻塞。 缺点:频繁发起系统调用,CPU占用率高,不适合高并发场景。

3. IO多路复用(Redis采用epoll实现)

定义:单个线程监听一批Socket,任一Socket数据就绪后主动通知进程,杜绝无效轮询。

  1. 执行阶段 阶段1:进程调用select/poll/epoll阻塞等待,内核监听批量Socket,有连接就绪则立即返回; 阶段2:遍历就绪Socket,调用recvfrom完成内核数据到用户空间的拷贝。

  2. select/poll/epoll 区别

    实现特点
    select/poll仅告知有连接就绪,不指定具体fd,用户需遍历全部Socket
    epoll(Redis默认)直接返回就绪的Socket,无需全量遍历,海量连接下性能最优

四、Redis网络事件模型

1. 三大事件处理器

  1. 连接应答处理器(tcpAcceptHandler):监听服务端口,接收客户端TCP连接。
  2. 命令请求处理器(readQueryFromClient):读取客户端指令;Redis 6.0使用多线程做命令解析,命令执行依旧单线程串行
  3. 命令回复处理器(sendReplyToClient):将执行结果返回客户端,Redis6及以上版本采用多线程异步回包。

2. 整体流程

客户端Socket → epoll事件监听 → 事件分发 → 三类处理器分工处理 → 执行结果写入缓冲区 → 多线程回包

五、面试简答总结

  1. Redis高性能三大原因:数据全存内存、单线程规避线程切换与锁开销、基于epoll的IO多路复用支撑高并发网络读写。
  2. IO多路复用:单线程监听海量Socket,仅在连接就绪时进行处理;epoll可精准定位就绪文件描述符,CPU利用率极高。

六、面试高频问题解析

  1. 问:为什么Redis单线程也能做到高性能?

    答: 第一,数据全程存内存,读写速度极快;第二,单线程避免了多线程上下文切换、锁竞争等开销;第三,采用epoll IO多路复用模型,单线程可高效处理海量并发连接。

  2. 问:简单介绍IO多路复用以及epoll的优势?

    答: IO多路复用指单线程同时监听多个网络连接,有数据就绪再处理。epoll相比select、poll,能够直接返回就绪的连接,不需要全量遍历,在海量连接场景下性能优势明显。

  3. 问:Redis6之后线程模型有什么变化?

    答: Redis6引入多线程,命令解析、结果回包使用多线程处理,但核心命令执行逻辑仍然是单线程串行执行,保证线程安全。

  4. 问:简述阻塞IO和非阻塞IO的弊端?

    答: 阻塞IO全程等待,单线程只能处理一个连接,并发差;非阻塞IO需要不断轮询,造成CPU空转、占用过高。

Powered by VitePress 1.6.4 | 持续更新中