当前位置: 首页 > news >正文

剥洋葱式推演:一步步彻底搞懂 Redis 的 I/O 多路复用

我们要回答的核心问题是:为什么 Redis 只有一个主线程,却能同时服务几万个客户端,且不被卡死?

为了搞懂这个,我们必须回到一切的起点——最原始的网络通信

第一步:认清物理现实(网络请求分为“等”和“做”)

假设我们写了一段最基础的网络服务器代码,只用一个单线程。当一个客户端(Client A)连接上来时,服务端要处理它的请求,必然要经历两个阶段:

  1. 等数据(Wait for data):数据从客户端通过网络电缆,慢慢悠悠地传到网卡,再进入操作系统的缓冲区。

  2. 做事情(Copy and Execute):数据到齐了,主线程把数据读进内存,执行命令(比如SET key value)。

痛点出现了:阶段 2 的执行速度在内存中是极快(微秒级)的;但是阶段 1 的“等”是受网络波动、用户输入速度影响的,可能是几秒甚至几分钟。 如果单线程在处理 Client A 时,Client A 一直不发数据,这个单线程就会一直卡在阶段 1(被阻塞休眠),此时哪怕 Client B 带着数据来了,单线程也无法去接待 Client B。这就是传统的同步阻塞 I/O (BIO)

第二步:常规解法与死胡同(多线程的代价)

单线程会被一个慢客户端卡死,那最直觉的解决办法是什么?多线程

来一个客户端,我就为它new一个专属的线程。

  • Client A 来,分配线程 1。线程 1 去慢慢等数据。

  • Client B 来,分配线程 2。线程 2 立刻处理。

看似完美,但为什么 Redis 不用?因为 Redis 的目标是同时处理 10 万个连接。如果开 10 万个线程:

  1. 内存爆炸:每个线程本身就要消耗内存。

  2. CPU 瘫痪(上下文切换):CPU 核心数有限,要在 10 万个线程之间来回切换,光是“切换”的动作就把 CPU 算力耗尽了,根本没时间执行真正的命令。

  3. 锁竞争:这么多线程同时修改内存里的数据,为了保证安全必须加锁,一加锁性能又暴跌。

结论:多线程是一条死胡同。Redis 决定死守“单线程”,避免锁和上下文切换。那么,单线程怎么解决被卡死的问题呢?

第三步:思维破局(非阻塞与多路复用)

既然单线程不能在某一个客户端上“傻等”,那就必须改变规则。

生活中的比喻:老师(单线程)收 30 个学生(客户端)的试卷。

  • 传统模式:老师站在学生 1 桌前,看着他写,写完收卷,再去学生 2 桌前。如果学生 1 写了半小时,老师就傻站半小时。(这就是刚才讲的 BIO)。

  • 无脑轮询模式(NIO /select/poll):老师不停地在教室里转圈:“你写完没?你写完没?”转了 100 圈,发现只有 1 个学生写完了。老师累得半死(CPU 空转占用极高)。

  • 多路复用模式(I/O Multiplexing):老师坐在讲台上喝茶。规定:谁写完了,就把手举起来(触发事件)。老师只要一看有人举手,就直接走过去收卷。

在这里:

  • 多路= 多个网络连接(30 个学生)

  • 复用= 复用同一个主线程(1 个老师) 这就是 I/O 多路复用的本质核心:用一个线程,集中监听多个连接的“就绪状态”。有数据来的,我才去处理;没数据来的,我绝不在你身上浪费时间。

第四步:底层的杀手锏(操作系统的epoll

上面比喻中的“多路复用”,在 Linux 操作系统底层,就是大名鼎鼎的epoll函数。

单线程的 Redis 把所有连接进来的客户端 Socket,全部交给了操作系统的epoll去管理。

  1. 红黑树监听:epoll在内核里维护了一棵红黑树,里面挂着所有连接的客户端。

  2. 事件驱动机制(绝杀技):当某一个客户端的网络数据到达网卡时,网卡会通过硬件中断告诉 CPU。操作系统底层会把这个处于活跃状态的连接,立刻放进一个名叫“就绪链表”的队列里。

  3. 精准打击:Redis 主线程只需每次去问epoll:“就绪链表里有东西吗?”有的话直接拿出来处理。时间复杂度从轮询的 O(N) 变成了 O(1)。

第五步:Redis 的最终拼图(Reactor 事件模型)

有了epoll作为底座,Redis 在自己代码里设计了一套完整的流水线,这就是Reactor 模式(文件事件处理器)

整个流水线如下:

  1. 大管家(多路复用程序):死死盯住epoll返回的就绪链表。

  2. 事件队列:大管家把那些发来数据、准备好的连接,排成一条长队(事件队列)。

  3. 单线程执行器(文件事件分派器):Redis 那个传说中的单线程,以极快的速度从队列中拿出一个个连接,执行对应的命令(因为是纯内存操作,这步极快),写回结果。然后再拿下一个。

总结串联

让我们把完整的逻辑链串起来: 为什么 Redis 单线程能抗住高并发? 因为它绝不把时间浪费在“等待网络传输”上。 它通过I/O 多路复用(epoll,让操作系统充当大管家,代替它监控成千上万的连接。 只有当数据真的到了网卡、准备就绪时,才会排成队列交给单线程处理。 单线程省去了所有的上下文切换和锁竞争,以纯内存的速度执行完毕,从而实现了看似违背常理的极致性能。

http://www.zskr.cn/news/1498887.html

相关文章:

  • macOS 27 Golden Gate支持调整iPhone镜像窗口比例
  • 宿州本地老牌黄金白银铂金回收门店权威排行 TOP5 2026 线下实体商家联系方式大全 - 中安检金银铂钻回收
  • 微信小程序计算机毕设之基于springboot+微信小程序的文化景区旅游微信小程序文化旅游小程序系统(完整前后端代码+说明文档+LW,调试定制等)
  • 2026年宁夏银川全屋定制装修服务商深度选购指南 - 优质企业观察收录
  • 他一开口,我就知道他很懂AI Agent
  • 一个零经验开发者用 AI 完成微信记账小程序的实践复盘
  • 2026年6月宿迁本地黄金铂金白银金条回收靠谱门店 TOP5 榜单+实体老店联系方式 + 详细地址 - 中业金奢再生回收中心
  • 金价还在跌!2026 杭州紧急行情:现在卖就是止损,再等可能更低 - 奢侈品回收评测
  • 爽WiFi产品拆解:一个香港WiFi蛋品牌的服务设计逻辑|选型参考
  • NSK BSS50100-2E 超高速滚珠丝杠技术详解
  • 影刀RPA完全指南_非技术人员学习自动化的心智模型
  • 【计算机毕业设计案例】基于springboot+微信小程序的文化旅游小程序系统(程序+文档+讲解+定制)
  • 2026山西地区配电箱厂家综合实力排行及选型参考指南 - 起跑123
  • 深入解析LPC55S3x:从Flexcomm到EdgeLock,如何高效利用外设与安全子系统
  • 从 PMF 到规模化:AI Agent Harness Engineering 创业全生命周期路线图
  • 2026全球AI大模型大战:OpenAI冲击IPO,Meta豪赌超级智能,AI Agent时代来了
  • VScode cmake mingw 使用opencv调用笔记本摄像头进行人脸识别,并生成动态库、静态库
  • 影刀RPA实操指南_1688商品数据自动化采集
  • 【知识图谱】语义本体的演进之路:从严谨到敏捷的范式转变
  • Python 异步编程从入门到实战:告别阻塞,让你的代码效率起飞
  • 昆明正规黄金回收,资质齐全,特种行业备案可查! - 开心测评
  • Java 8 Optional 深度指南:告别空指针,解锁链式编程
  • 团队协作必看:如何用.eslintrc和.prettierrc配置文件根治代码风格‘打架’问题
  • MR-ROBOT靶机深度复盘:除了拿Flag,我们还能学到哪些实战渗透思路?
  • 基于 Harmony 6.0 应用的笔记与思维导图应用首页实现
  • 手把手教你用TI C2000 Ware库函数重构F28377x CAN通信代码(附中断配置)
  • Java Swing 图形界面编程
  • 广州闲置名包出手,认准这家口碑优质回收门店 - 开心测评
  • 别再被旧教程坑了!InVEST 3.10.2新版生境质量模块保姆级配置指南(附正确表格模板)
  • 手机安装Appium Settings后闪退-最简单解决方式