一句话先讲清楚
Redis 的核心命令执行线程是单线程,但 Redis整体不是单线程程序;
1. “单线程”到底指哪一部分?
Redis 这个主线程,叫事件循环线程(main thread),负责:
- 接收客户端连接、读网络请求
- 执行所有 Redis 命令(get、set、incr、hgetall 等)✅ 这部分是串行
- 把命令结果写回客户端
✅ 所有读写命令,在这个线程里是排队执行,同一时刻只能跑一条命令
⚠️ 但是下面这些不在这个单线程里跑:
- RDB 持久化:fork 子进程
- AOF 重写:fork 子进程
- 异步IO(6.0+ 多线程IO):网络读、写缓冲区交给IO线程
- 大key删除、lazyfree:后台异步线程释放内存
重点:命令执行逻辑仍然是单线程!6.0的多线程只是网络IO多线程,不是命令并行执行。
2. 那单线程串行,量大了为啥不会直接卡死
① Redis 是内存数据库,命令本身极快
数据都在内存,没有磁盘IO开销。一条简单get/set就是内存寻址,纳秒~微秒级别。 单线程跑,每秒轻松 10w+ 简单命令。
瓶颈不在CPU,而在网络。
② 单线程避开了锁竞争开销(这就是它快的核心原因之一)
多线程操作共享内存,要加锁、解锁、CPU上下文切换,有损耗。 单线程执行命令,不需要对数据结构加锁,天然没有并发竞争问题,代码简单、开销极低。 这就是官方选择单线程跑命令的初衷。
3. 并发是怎么实现的?(IO多路复用)
很多人混淆:单线程 ≠ 不能处理多客户端并发
Redis 用IO多路复用(epoll/kqueue)主线程可以同时监听成千上万个客户端socket,哪个客户端有请求来了,就拿出来执行命令。 不是一个客户端占着线程不放,是事件驱动:来了请求就处理,处理完立刻回去等待下一个事件。
类比:饭店只有1个服务员(命令线程),但是有很多桌客人(客户端);客人不喊他,他就等着;客人喊了,他就快速处理完这一单,再处理下一桌。 如果有一桌客人特别磨叽(慢命令),所有桌子都等着。
多路 = 多个 socket 连接;复用 = 复用这一个线程