别再误会了!Redis 6.0 的多线程,和你想象的完全不一样
技术解析
核心误区:Redis 6.0是完全多线程的吗?
No. Redis 6.0引入的多线程,只用于网络I/O的读写和数据的解析。而核心的命令执行(比如 GET
, SET
, HGETALL
等)依然是单线程的。
Redis的架构演进,就像是把一个复杂的任务分解成:“听你说话 -> 思考并做事 -> 回答你” 这三个步骤。
• 听你说话:接收网络请求,解析命令。
• 思考并做事:执行命令。
• 回答你:将结果返回给客户端。
在Redis 6.0之前,这三个步骤都由一个单线程完成。这个单线程模型在CPU计算上非常高效,但它最大的瓶颈在于“听你说话”和“回答你”这两个网络I/O环节。
Redis 6.0的多线程优化,只针对**“听你说话”和“回答你”这两个网络I/O环节**进行了并行化,而最核心的“思考并做事”环节依然保留了单线程。
Redis 6.0多线程的执行流程
1. 主线程 (Main Thread)
• 监听连接: 负责
accept()
新的客户端连接。• I/O多路复用: 负责
epoll_wait
等系统调用,等待网络事件的发生。
2. I/O线程 (Worker Threads)
• 处理网络读写: 主线程将准备就绪的Socket(已收到数据或可写入数据)分发给这些I/O线程。
• 解析请求: I/O线程负责从Socket中读取数据,解析出命令。
• 发送响应: I/O线程负责将执行结果写入Socket,发送给客户端。
3. 主线程 (Main Thread) 再次登场
• 执行命令: I/O线程解析完命令后,会将命令提交给主线程。主线程仍然是唯一的命令执行者。它会将所有客户端提交的命令,按顺序、单线程地执行,保证了Redis命令的原子性和数据一致性,避免了锁的开销。
这个过程就像一个经典的生产者-消费者模型:I/O线程作为生产者,负责处理网络数据包,将命令“生产”出来;主线程作为消费者,负责从队列中取出命令并执行。
配置参数
Redis 6.0的多线程功能默认是关闭的。你可以通过以下参数来开启和配置:
# 开启多线程
io-threads-do-reads yes
# 设置I/O线程数量,建议设置为CPU核心数-2或-4
io-threads 4
故事场景:米其林餐厅的“主厨与服务员”模式
你(Redis)是一家米其林三星餐厅的主厨(Main Thread)。你以精湛的厨艺(执行命令)闻名,但你一次只能做一道菜,并且绝不允许任何人插手你的烹饪过程(单线程执行)。
传统模式 (Redis 6.0之前): “主厨事必躬亲”
• 工作流程:
你既是主厨,又是餐厅的服务员。1. 接待顾客: 你亲自到门口迎接顾客(
accept
连接)。2. 听顾客点单: 你亲自听顾客点单,并把菜单写下来(网络I/O读写)。
3. 烹饪: 你回到厨房,专心致志地做菜(执行命令)。
4. 上菜: 你亲自把菜端给顾客,并收盘子(网络I/O读写)。
• 瓶颈:
你做菜的速度很快,但由于要花大量时间在接待、听单、上菜这些琐碎的体力活上,你大部分时间都耗在了餐厅大堂和顾客周旋,真正花在厨房里做菜的时间反而很少。这导致餐厅的整体效率不高。
现代模式 (Redis 6.0之后): “主厨与多位服务员”模式
为了解决这个瓶颈,你雇佣了一个专业的服务员团队(I/O Threads)。
• 工作流程:
1. 总指挥: 你(主厨)依然坐在厨房里,通过一个监视器(
epoll
),同时关注着所有餐桌(Socket)。2. 服务员团队: 当某个餐桌的顾客(客户端)点完单或需要上菜时,监视器会提醒你。
3. 分派任务: 你会立刻把这个任务派给一个空闲的服务员。服务员小李去收菜单(网络I/O读),服务员小张去上菜(网络I/O写)。
4. 主厨的核心工作: 服务员团队(
I/O Threads
)将收到的菜单(命令)送回厨房,你(主厨)仍然是唯一的烹饪者。你按顺序、单线程地做菜,并把菜品放在“上菜口”。5. 服务员团队再次出动: 菜做好后,服务员团队会再次从“上菜口”把菜端走,送到对应的餐桌。
• 优化效果:
• 主厨效率飞升: 你(主厨)从繁重的I/O杂活中彻底解脱出来,可以全身心地投入到你最擅长的烹饪(命令执行)上。
• 整体效率提升: 即使来了100桌客人,只要你有足够多的服务员,他们可以并行地收单、上菜,而主厨则可以稳定、高速地处理源源不断的菜单。
故事总结:
特性 | Redis 6.0之前 | Redis 6.0之后 |
核心执行 | ✅ 单线程 (主厨亲自做饭) | ✅ 单线程 (主厨依然是唯一烹饪者) |
网络I/O | ❌ 单线程 (主厨兼服务员) | ✅ 多线程 (专业服务员团队分工合作) |
工作模式 | 命令执行被I/O阻塞 | I/O和命令执行分离 |
核心比喻 | 主厨一人包办一切 | 主厨专心烹饪,服务员团队处理杂务 |
结论:
Redis 6.0引入多线程,并非要推翻其赖以成名的“单线程模型”。相反,它是一种精准的、有针对性的优化。通过将单线程模型中唯一的瓶颈——网络I/O,剥离并交由多线程并行处理,使得Redis在不牺牲原子性、简-洁性的前提下,将性能推向了新的高度。