Redis核心处理网络请求、执行命令的主线程是单线程,但它并不是整个程序只有一个线程,持久化、异步删除、集群同步等操作都会启用子线程 / 后台线程。 它单线程还能做到高性能,核心有下面几点原因:
1. 纯内存操作,读写速度本身天花板很高
Redis 所有数据都存放在内存中,内存 IO 速度是磁盘的成千上万倍。 数据库需要频繁刷磁盘、做页交换,而 Redis 不需要落盘参与常规读写,命令执行几乎没有慢速 IO 阻塞,单线程完全能扛住海量操作。
2. 单线程避免了多线程的开销与竞争
多线程并发会带来几个很重的损耗,Redis 单线程直接规避:
- 不需要频繁创建、销毁线程;
- 不用加锁、解锁,不存在锁竞争、上下文切换消耗 CPU;
- 没有多线程共享资源带来的竞态问题,底层数据结构不用复杂同步机制。 单线程串行执行命令,天然线程安全,省去大量并发同步开销。
3. 采用 IO 多路复用模型,高性能处理上万连接
这是最关键的一点,单线程不代表只能处理一个客户端连接。 Redis 底层使用 epoll(Linux)/kqueue/select IO 多路复用:
- 一个线程同时监听成千上百个 socket 连接;
- 只有当某个客户端有读写事件就绪时,才去处理,没有事件时完全阻塞等待,不消耗 CPU;
- 基于事件驱动,不会为每个连接开辟线程,极低资源占用支撑高并发连接。
简单理解:一个售票窗口(单线程),同时监听所有排队的人,谁准备好了就处理谁,不用一人开一个窗口。
4. 高效的数据结构设计
Redis 每种数据结构都是针对性优化的高性能实现:
- String:简单动态字符串 SDS,减少内存拷贝;
- List:快速链表、压缩列表;
- Hash/Set/ZSet:跳表、哈希表,查询、增删时间复杂度大多 O (1)、O (logn); 底层封装了很多内存优化、预分配、缩容策略,命令运算本身极快,单线程处理毫无压力。
5. 避免系统调用与内存拷贝(零拷贝思想)
- 读取数据回复客户端时,使用系统 sendfile,内核态直接传输,减少用户态、内核态来回拷贝;
- SDS、压缩列表减少多余内存复制,降低 CPU 耗时; 少量内存操作,单线程执行效率极高。
6. 耗时操作全部交给后台子线程,不阻塞主线程
虽然命令执行是单线程,但重操作绝不占用主线程:
- RDB 持久化:fork 子进程完成;
- AOF 刷盘、AOF 重写:后台线程;
- UNLINK 大键异步释放内存、大集合删除:后台线程;
- 文件同步、集群数据同步:独立线程; 主线程只负责简单命令处理,慢操作全部异步剥离,不会阻塞读写。
7. Redis6 引入多线程 IO(补充加分)
Redis6 之后新增IO 多线程,进一步提升网络读写性能:
- 命令解析、执行依旧是单线程;
- 网络数据的读缓冲区、写回响应交给多线程并行处理; 解决大流量下网络 IO 成为瓶颈的问题,进一步拉高 QPS 上限。
补充:单线程的短板
单线程不是万能的,如果执行耗时极高的命令,会阻塞整个实例: 比如 keys *、hgetall、超大集合遍历、长时间 Lua 脚本,会卡住主线程,所有客户端请求等待。 开发规范:线上禁止全量遍历命令,拆分大 key,精简 Lua 执行逻辑。
简短总结
Redis 命令执行主线程单线程却很快,核心五点:
- 全部数据内存存储,无磁盘慢速 IO;
- IO 多路复用,单线程管理海量客户端连接;
- 单线程无锁竞争、无线程切换开销;
- 底层高度优化的高效数据结构;
- 持久化、大键删除等耗时操作异步子线程执行; Redis6 还增加 IO 多线程优化网络吞吐,同时要注意避免慢命令阻塞主线程。