Redis的IO模型与多路复用
Redis的IO模型与多路复用
概念解释
首先要明确一点,redis的单线程指的是redis网络IO和键值对的读写是在一个线程完成的。而其他的功能,比如持久化等是在其他线程中完成。在redis6.0中,引入了多线程的支持
传统的单线程会有问题,比如某一个操作阻塞了,导致整个进程无法对外提供服务。进程的阻塞是进程自身的一种主动行为,也因此只有处于运行态的进程(获得了CPU资源),才可能将其转为阻塞状态。当进程进入阻塞状态,是不占用CPU资源的。
redis为了解决这个问题,提出了IO多路复用
在介绍多路复用前,我们要先明确什么是文件描述符
文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着 件描述符展开。但是文件描述符这一概念往往只适用于UNIX、Linux这样的操作系统。
现在我们就可以解释什么多路复用了
所谓的多路,就是网络的连接。而复用指的是对一个线程而言
IO 多路复用是一种同步IO模型,实现一个线程可以监视多个文件句柄,一旦某个文件句柄就绪,就能够通知应用程序进行相应的读写操作。没有文件句柄就绪就会阻塞应用程序,交出CPU。
服务器端采用单线程通过select/poll/epoll
等系统调用获取文件描述符列表,遍历有事件的文件描述符进行accept/recv/send
,使其能支持更多的并发连接请求。
IO多路复用的实现方式
- select
- poll
- epoll
redis默认的实现方式是epoll,原因下面会讲
select
它只能遍历所有的流才能找出其中有IO事件发生的,所以同时处理的流越多,耗费的时间越长。因为整个时间复杂度是O(N)的
缺点:对socket的扫描是线性扫描,时间比较长;单个进程所能打开的文件描述符是有限制的。每次调用select的时候都需要从用户态拷贝到内核态,在文件描述符比较多的时候开销很大
poll
相比于select,poll最大的特点就是没有连接数量的限制
缺点同select
epoll
优点:
没有连接数量的限制,连接上限远远超过2048,主要取决于内存大小。
它只监听活跃的连接,效率更高。io的效率不随着连接总数而下降。在这一点上就远远超过了select和poll
共享内存来避免内存拷贝,实际上不管是哪种实现方式,都需要内核把文件描述符通知给用户空间。这样一来避免内存拷贝就很重要
epoll的执行方式和select,poll都不一样,它在内核中申请了一个简易的文件系统(b+树实现),把原来的调用分为三个部分:
epoll_create()
epoll_ctl()
epoll_wait()
调用 epoll_create
时,内核帮我们在 epoll 文件系统里建立 file 结点,内核缓存中建立 socket 红黑树,除此之外,还会再建立一个用于存储准备就绪事件的链表。
执行 epoll_ctl
时,如果增加就绪事件的 socket 句柄,则需要检查在红黑树中是否存在,存在立即返回,不存在则添加到树干上,然后向内核注册回调函数,用于当中断事件来临时向准备就绪链表中插入数据。
epoll_wait
调用时,仅仅观察这个 list 链表里有没有数据即可,有数据就返回,没有数据就 sleep,等到 timeout 时间到后,即使链表没数据也返回。
epoll_wait
的执行过程相当于以往调用 select/poll,但 epoll 的效率高得多。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性