众力资讯网

为什么 Redis 单线程却比多线程还快?真实原因震撼我

大家好,我是小米,一个在互联网研发里滚了十来年、对技术既执着又好奇、写代码比写周报开心的 31 岁男人。今天这篇文章想



大家好,我是小米,一个在互联网研发里滚了十来年、对技术既执着又好奇、写代码比写周报开心的 31 岁男人。

今天这篇文章想和你聊聊一个面试“高频炸裂”的问题——Redis 线程模型到底是怎么回事?

别小看这个问题,它比你想象的“坏”多了。

有一次我去一家还算知名的互联网公司面试,面试官是个戴着黑框眼镜、看起来很斯文的小哥,但当他一开口,我立马意识到这人不好对付。

他慢慢抬头看我一眼,淡定问道:

“我们聊点简单的吧。Redis 是单线程吗?为什么单线程还能这么快?它的线程模型你能讲讲吗?”

这一瞬间,我脑袋里警报大响:完了,这是送命题。

不过没办法,程序员嘛,刀山火海也得硬冲。于是我脑内迅速召唤出我多年研究 Redis 的记忆碎片,然后把故事讲了出来。

今天我就把这套“面试官听了会满意,你听了会拍大腿”的 Redis 线程模型解析,用轻松、故事化的方式讲给你听。

你看完以后,下次面试官问这个,你直接微微一笑,然后把本文的精髓娓娓道来,稳了。

Redis 线程模型不是“单线程”这么简单

很多人对 Redis 的第一印象就是——

“Redis 是单线程的。”

这句话其实对,也不对。正确来说:

Redis 的核心逻辑处理是单线程:也就是处理命令的主线程只有一个。

Redis 并不是只有一个线程:IO、持久化、集群、异步删除、过期清理,这些都有辅助线程。

那它为什么要“装”成单线程?这是因为 Redis 的核心哲学是:快。

越简单,越能快得起来。但是!它到底怎么做到“一线程干掉多线程”?这就得讲一个行业传奇的故事了。

故事从一次我面试时的“尴尬瞬间”说起

那天面试官继续问我:

“Redis 单线程为什么性能这么高?”

我心里想着:

兄弟你知道这问题有多大吗?这背后涉及 IO 模型、数据结构、内存布局、CPU Cache、锁竞争、系统调用、事件循环……

但没办法,我又不能回他一句“因为够简单”,于是我深吸一口气开始讲故事:

Redis 线程模型的核心:Reactor 单线程事件循环

Redis 的主线程使用的是 基于 Reactor 模式的事件驱动机制。简单比喻一下:

Redis 的主线程就像餐馆里 一位非常高效的厨师。

所有点单都由他接收

所有炒菜他一个人完成

他速度极快,手法干净利落

菜都是提前准备好的,锅有预热,酱料放好

没有另外一个厨师跟他抢锅

没有人跟他抢勺子

所以:

他一个人反而比三个厨师互相碰锅、抢位置搞得更快。

Redis 主线程干的活其实就三件:

读:接收 socket 的数据(比如 SET、GET、HSET 指令)

处理:执行具体命令逻辑(用 C 写的操作内存的代码,快得飞起)

写:把结果返回给客户端

这一套动作全部在 一个线程的事件循环(Event Loop)里完成。事件循环大概是这样的:

是不是非常 Node.js?没错,Redis 和 Node.js 都是典型的基于 Reactor 的事件驱动模型。

为什么单线程还能这么快?

当我把上面的结构说给面试官听后,他满意地点点头,然后继续发问:

“那为什么 Redis 单线程却比线程池模型还快?”

你看,这才真正进入灵魂。于是我继续解释:

1. Redis 完全基于内存操作

内存是纳秒级的。磁盘是毫秒级的。差了 100 万倍。你说快不快?

2. 单线程避免上下文切换

线程多了意味着:

CPU 上下文切换

内核态 ↔ 用户态频繁切换

线程调度带来的 cache miss

而这些开销其实非常大。Redis 一条线程处理所有逻辑(不含持久化),没有切换成本,效率自然高得吓人。

3. 使用高效 IO 多路复用

Redis 使用:

epoll(Linux)

kqueue(BSD)

select(旧系统)

这让 Redis 能够:

在单线程中同时管理成千上万个客户端连接。

4. 数据结构设计极其优秀

Redis 内部的数据结构全部是 C 实现的:

dict(哈希表)

skiplist(跳表)

sds(字符串)

quicklist、ziplist、listpack

radix tree

这些结构都是为性能优化过的:

避免额外指针

连续内存布局

减少 malloc

减少 cache miss

O(1) 或 O(log n) 时间复杂度

CPU Cache 命中率高,性能自然爆炸。

5. 命令本身非常高效

Redis 的所有命令都是原子操作,C 函数一次干到底。不像数据库还要:

SQL 解析

SQL 优化

锁管理

事务协调

权限检查

Redis 直接干,不废话。

6. 功能分线程,不干扰主线程

虽然主线程单线程,但其他耗时任务都被“外包”了:

主线程只处理核心逻辑,不被拖慢。所以 Redis 才能做到:

单线程,却比大部分多线程系统更快。

Redis 真正的线程模型(从 Redis 6 开始)

面试官听完我一大段输出后,突然问了一个升级版问题:

“那 Redis 6 呢?还是单线程吗?”

好家伙,这人绝对是想把我拿下。于是我继续解释:

Redis 6 有多线程,但不处理命令

Redis 6 引入了 I/O 多线程:

接收网络请求:多线程

发送响应:多线程

命令执行:依旧单线程

为什么?因为 Redis 的核心命令处理继续保持单线程的设计理念:

不用加锁

不用事务冲突

没有竞争

没有抢占

但网络 I/O 是可以多线程并发的,所以引入了多线程 I/O 来提升吞吐。

一句话总结:

Redis 6:I/O 多线程,命令单线程。

完整总结:Redis 线程模型的全景结构图

如果我把 Redis 做成一张组织架构表,大概是这样的:

总结一句话:

Redis 的“单线程”指的是:命令处理线程是单线程。但整个 Redis 不是单线程。

如何向面试官完美回答 Redis 线程模型?

下面给你一个“面试必杀版答案”,你背下来就赢了:

标准版(两分钟)

Redis 的核心命令处理是单线程,通过基于 Reactor 的事件循环模型来处理网络事件、命令执行和响应输出。

它的性能高主要依赖于:纯内存操作、高效数据结构、IO 多路复用、避免线程切换、命令简单高效。

虽然核心逻辑是单线程,但 Redis 内部还有其他线程处理异步删除、AOF 刷盘、RDB 持久化等耗时操作,从而保证主线程不被阻塞。

从 Redis 6 开始引入了 I/O 多线程,用于网络读写加速,但命令执行仍保持单线程,以避免加锁和竞争。

面试官听了会很舒服的版本(10 秒钟)

Redis 的命令执行是单线程的,但 Redis 不是单线程系统。

它使用事件驱动模型执行命令,同时把耗时任务丢给后台线程。

Redis 6 之后网络 I/O 支持多线程,但核心逻辑仍然单线程。

简单 + 内存 + 高效数据结构 = 它特别快。

故事的结尾:面试官点头,我拿到了 Offer

当我把这些讲完之后,面试官露出满意的微笑:

“讲得不错,可以。”

那一刻,我偷偷握紧拳头:

果然,技术实力才是最硬的底气。

后来我也顺利拿到了 Offer。

Redis 的线程模型看似简单,但背后是一整套极致追求性能的架构哲学:

单线程处理核心逻辑

多线程处理耗时任务

内存存储

高效数据结构

IO 多路复用

零锁模型

最大程度利用 CPU Cache

真正的工程之美就在这里。

END

如果你看到这里,恭喜你,你完全具备了在面试中自信讲解 Redis 线程模型的能力。以后面试官再问你:

“Redis 是不是单线程?为什么这么快?线程模型怎么实现的?”

你只需要轻轻一笑:

“要不我给你讲讲 Redis 的 Reactor 模型?”

“顺便聊聊 Redis 6 的多线程 I/O?”

“要不连 IO 多路复用我也给你带一遍?”

稳得不能再稳。