1. 核心概念

在 Redis 6.0 之前,Redis 的核心网络模型是 单线程 的(基于 Reactor 模式)。这意味着接收客户端请求、解析请求、执行命令、发送响应都在同一个线程中完成。

Redis 6.0 引入了多线程 I/O,但请注意:Redis 的命令执行(Command Execution)依然是单线程的

引入多线程的主要目的是为了解决 网络 I/O 的瓶颈。随着硬件性能提升,Redis 的性能瓶颈逐渐从 CPU 转向了网络读取和写入(Syscall 开销、协议解析、数据拷贝)。

2. 原理与源码关键点

2.1 为什么之前是单线程?

  • CPU 不是瓶颈:Redis 是内存数据库,绝大多数操作极快,瓶颈通常在于内存大小或网络带宽。
  • 避免复杂性:单线程避免了死锁、上下文切换、竞态条件,代码更易维护。

2.2 6.0 的多线程模型

Redis 6.0 的多线程仅用于处理 网络 I/O 任务:

  1. 网络读取(Socket Read):多线程并行读取客户端 Socket 数据。
  2. 协议解析(Protocol Parsing):多线程并行解析命令。
  3. 命令执行(Command Execution)依然由主线程串行执行。这保证了原子性,无需复杂的锁机制。
  4. 网络写入(Socket Write):多线程并行将响应数据写入 Socket。

2.3 源码流程简述

主线程在处理事件循环时:

  1. 将等待读取的客户端连接分配给一组 IO 线程。
  2. 主线程阻塞等待所有 IO 线程完成读取和解析。
  3. 主线程串行执行解析好的命令。
  4. 主线程将响应数据分配给 IO 线程。
  5. 主线程阻塞等待所有 IO 线程完成写入。

3. 性能优化与考量

  • 性能提升:官方测试显示,开启多线程后,Redis 的吞吐量(QPS)可以提升 2-3 倍
  • 配置开启:默认情况下多线程是关闭的。需要在 redis.conf 中配置:
    io-threads-do-reads yes
    io-threads 4  # 建议设置为 CPU 核心数的 3/4
    
  • 线程安全:由于命令执行依然是单线程,因此用户无需担心 Lua 脚本、事务的原子性问题,也不需要修改现有的客户端代码。

4. 总结

Redis 6.0 引入多线程是为了突破网络 I/O 的性能瓶颈,而非 CPU 计算瓶颈。

面试回答示例:

“Redis 6.0 引入多线程主要是为了解决网络 I/O 读写带来的性能瓶颈。 它的关键点在于:I/O 多线程,执行单线程。即使用多个线程并行处理客户端的网络数据读取、协议解析和数据回写,但指令的实际执行依然由主线程串行完成。 这种设计既保留了 Redis 单线程模型的简单性(无锁、无竞态),又利用多核优势显著提升了高并发下的吞吐量。”