Redis NIO多路复用
🍥 一句话总结(真正的核心)
Redis 用 epoll 的 I/O 多路复用机制,让单线程也能同时处理成千上万连接,而不用为每个连接创建线程。
换句话说:
- 不阻塞
- 不多线程
- 不并发锁
- 极高并发能力
这是 Redis 快的核心基础之一。
🧵 Redis 为什么能用单线程支撑高并发?
因为:
Redis 不是为每个连接创建线程,而是使用 epoll 监听多个连接的读写事件。
只要某个连接“准备好了”,Redis 才处理它。
这就叫 I/O 多路复用模型。
🟦 1. 什么是 I/O 多路复用?
关键字:One Thread + Many Connections + epoll 事件触发
示意图(你脑子里一定得有这个):
┌─────────────┐
│ Redis │ 单线程
└──────┬──────┘
│
epoll_wait
│
┌───────────────┴─────────────────┐
│ │ │ │
conn1 (读就绪) conn2 (读就绪) conn3 … connN
Redis 的事件循环主要做两件事:
- epoll 等待 socket 事件(不会阻塞 CPU)
- 哪个连接就绪,就处理哪个连接(执行命令)
没有就绪事件时 Redis 是 idle,不浪费 CPU。
🟩 2. Redis 的事件驱动模型(Event Loop)
Redis 内部有一个 "AE"(Abstract Event)事件框架:
while(true):
处理定时任务
处理网络 I/O (epoll)
执行客户端命令
两类事件:
- 文件事件(File Events):网络连接相关,靠 epoll
- 时间事件(Time Events):定时任务(过期 key 检查、AOF 刷盘、Cluster 心跳)
你可以理解为:
Redis = 一个加强版 Nginx + 数据结构存储引擎
🟥 3. 多路复用的核心:epoll
Redis 使用 Linux 的 epoll:
- 使用 epoll_create 创建实例
- 所有客户端 socket 注册到 epoll
- 使用 epoll_wait 阻塞等待事件发生
- 某个 socket 有读写时 → 回调对应的处理函数
简单流程:
客户端发送命令
↓
socket 缓冲区变为可读
↓
epoll_wait 返回事件
↓
Redis 单线程读取数据 + 执行命令
↓
写回结果
整个过程中:
❌ 没有一个连接对应一个线程
✔ 所有连接共享一个事件循环
🟧 4. 为什么 epoll 如此关键?
看看没有 epoll 的老旧模型:
(1)每连接一个线程?
- 成百上千线程上下文切换
- CPU 被抢占
❌ Redis 不干
(2)select/poll?
- 每次都要把所有 FD 扫一遍
- O(n) 遍历
❌ 高并发下效率崩溃
(3)epoll 的优势:
- O(1) 级监听事件
- 支持海量连接
- 基于回调
- 事件驱动,很轻量
这是 Redis 能在单线程达到 10+ 万 QPS 的基础。
🟨 5. 多路复用 + 单线程 = 无锁 + 极高效率
Redis 只有一个线程执行命令,所以:
- 无加锁
- 无竞争
- 无线程切换
- 无内存同步开销
几乎所有 CPU 被用于执行命令,而不是处理线程调度。
这就是 Redis 的 “极简哲学”:
复杂性交给操作系统(epoll),Redis 专心执行逻辑。
🟫 6. 多路复用执行一次命令的完整流程(图)
┌──────────────────────────┐
│ EventLoop │
└────────────┬─────────────┘
│
epoll_wait
│
┌──────────────┼────────────────┐
│ │ │
conn1 ready conn2 ready … connN ready
│
读取命令(read)
│
解析命令(parse)
│
执行命令(execute)
│
写回结果(write)
所有 I/O 都是非阻塞的。
🧠 7. 面试高级回答(别人都不会的版本)
Redis 使用 epoll 作为 NIO 多路复用器,对所有客户端 socket 注册读写事件,通过单线程事件循环处理所有就绪事件,不需要额外的线程池,也没有锁竞争。事件驱动模型让 Redis 单线程也能轻松支撑十万级连接,这是 Redis 高性能的重要基础。
这句话你背一下,绝杀。
🧩 8. 总结一句话(记住)
Redis 的单线程之所以快,就是因为 epoll + 非阻塞 I/O + 事件驱动,让它能轻松处理海量连接,而无需开多线程、也没有锁开销。
浙公网安备 33010602011771号