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 的效率高得多。

posted @   liubing0806  阅读(359)  评论(0编辑  收藏  举报
编辑推荐:
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
阅读排行:
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
点击右上角即可分享
微信分享提示
主题色彩