先说结论。Redis 快,不是因为「单线程」本身快,而是三件事叠在一起:数据在内存、单线程避开了上下文切换和锁竞争、IO 多路复用让一个线程扛住海量连接。
前两条面试官基本不会深问。那问题来了------第三点 IO 多路复用才是真正的考点。下面把它一次讲透。
一、快的三条根因
第一,数据在内存。
这是最主要的原因。
内存读写是纳秒级,磁盘是毫秒级,差了几个数量级。
Redis 所有操作都基于内存,天然就快。
第二,单线程反而省了开销。
多线程听着快,但线程数超过 CPU 核数就要上下文切换,切换本身耗性能。
更麻烦的是线程安全:
多线程共享数据就得上锁,锁竞争又会把并行逼成串行。
Redis 干脆单线程执行命令,没有切换、没有锁,简单直接。
第三,IO 多路复用 + 非阻塞 IO。
这是它能用单线程扛高并发的关键,也是下面要展开的重点。
二、瓶颈在网络,不在执行
要理解第三点,先建立一个判断:
既然命令都是内存操作,执行本身就极快,那 Redis 的性能瓶颈其实不是 CPU,而是网络延迟。
说白了,慢的不是「算」,是「等数据来、等数据走」。
所以优化的方向不是多开线程去算,而是别让线程干等网络。
IO 多路复用解决的就是这件事。
三、IO 效率的两个敌人
讲清多路复用之前,得先知道 IO 慢在哪。
Linux 下,进程分用户空间和内核空间:
用户空间权限低,不能直接操作网卡、磁盘这些硬件,必须借助内核空间的接口。
发一条消息,数据要从用户缓冲区拷到内核缓冲区,再由内核写进网卡;
收一条消息,反过来从网卡读到内核缓冲区,再拷回用户缓冲区。
整个过程里,拖慢 IO 的有两件事:
- 无效等待:内核还没收到数据,用户进程只能干等。
- 数据拷贝:用户态和内核态之间来回拷,拷贝期间进程也是阻塞的。
后面几种 IO 模型,都是在和这两件事较劲。

四、三种 IO 模型:阻塞、非阻塞、多路复用
| 模型 | 第一阶段(等数据) | 第二阶段(拷数据) | 问题 |
|---|---|---|---|
| 阻塞 IO | 阻塞,干等 | 阻塞 | 两阶段都卡,一个连接卡住全卡 |
| 非阻塞 IO | 非阻塞,但轮询 | 阻塞 | 轮询造成 CPU 空转 |
| IO 多路复用 | 阻塞在监听,但一次管多个 | 阻塞 | 单线程同时管多个连接,效率高 |
阻塞 IO 最直白:
等数据就绪要等,数据从内核拷到用户也要等,两个阶段都阻塞。
更糟的是它一次只能盯一个连接,这个连接在等数据,后面排队的连接全得跟着等。
非阻塞 IO 把第一阶段变成「不停轮询」:
内核没数据就立刻返回,进程反复问「好了没」。
表面不阻塞了,但本质是盲等,CPU 被空转耗光,性能也没起来。
IO 多路复用换了个思路:
一个线程同时监听一堆 Socket,谁就绪通知谁,不用傻等,也不用盲问。

五、select/poll 与 epoll 的差别
多路复用在 Linux 上有三种实现:select、poll、epoll。前两个是一路人,epoll 是升级版。
打个比方。
餐厅里很多桌客人要点餐:
- select / poll 像每张桌上装了个按钮,全连到服务员头顶的一盏灯。任意一位按了,灯就亮,但服务员不知道是谁按的,只能一桌一桌去问「你要点餐吗」,找到为止。连接越多,遍历越慢。
- epoll 像按钮直接连到服务员面前的屏幕,谁按了,屏幕上直接显示「3 号桌就绪」。服务员不用遍历,直接去处理。
差别就在这:
select/poll 只告诉你「有 Socket 就绪」,但不说是哪个,你只能逐个翻;
epoll 在通知的同时把就绪的 Socket 直接交给你,省掉了遍历。
这也是 Redis 在高并发下依然稳的关键。

六、Redis 的网络模型:多路复用 + 事件派发
Redis 的网络模型,就是 IO 多路复用,再叠一套自己的事件派发机制。
多路复用负责监听客户端连接(每一个 Socket 连接)。
连接上之后会有不同事件:
有读请求,有写请求。
多路复用把就绪的连接和事件捞出来,派发给对应的事件处理器:
- 连接应答处理器:处理客户端的连接应答。
- 命令请求处理器:接收客户端参数、转成 Redis 指令、执行、产出结果。
- 命令回复处理器:把结果响应回客户端。
一句话:
请求进来交给多路复用做事件监听,提前定义好各种处理器,什么事件就派发给什么处理器。

七、Redis 6.0 之后为什么又有多线程?
注意,上面说的都是单线程模型。
Redis 6.0 引入了多线程,但只加在两处网络 IO 上:
- 接收网络请求、解析命令时,多线程并行把客户端发来的字节流解析成 Redis 命令。
- 响应结果输出时,多线程并行把结果写回网络。
命令的执行仍然是主线程串行跑,线程安全、基于内存、不影响性能。
真正拖慢的,是「收字节」和「发字节」这两段网络 IO,所以多线程只加在这里。
到这里就能回答面试官了:
Redis 用单线程执行命令,靠 IO 多路复用 + 事件派发扛住高并发;6.0 后又把网络收发的 IO 多线程化,进一步压榨网络延迟带来的损耗。