原创

redis网络模型-IO多路复用-事件通知机制以及web服务流程


IO多路复用-事件通知机制

当FD有数据可读时,我们调用epoll_wait就可以得到通知。但是事件通知的模式有两种:

  • LevelTriggered:简称LT。当FD有数据可读时,会重复通知多次,直至数据处理完成。是Epoll的默认模式。
  • EdgeTriggered:简称ET。当FD有数据可读时,只会被通知一次,不管数据是否处理完成。

举个栗子:

  1. 假设一个客户端socket对应的FD已经注册到了epoll实例中
  2. 客户端socket发送了2kb的数据
  3. 服务端调用epoll_wait,得到通知说FD就绪
  4. 服务端从FD读取了1kb数据
  5. 回到步骤3(再次调用epoll_wait,形成循环)

微信截图_20230214214039

  • LT的问题

    由于重复通知其效率会受影响

    LT可能会出现惊群现象,当一个fd就绪通知完成后他这个fd信息还会存在list_head链表中这也就导致所有监听这个fd的进程最后都会被通知到,也就是说一个fd就绪所有监听线程都会被唤醒,ET就不会有这个现象它通知完就直接移除了不会保留fd

  • ET的问题

    当有多个fd就绪通知服务端调用epoll_wait,由于ET只通知一次而数据量超过服务端数据读取上限没有一次读取完,再次读取时剩余的fd已经被移除掉了,造成残留数据问题

    残留数据问题解决方案

    方案一:

    在第一次读完list_head中的fd数据后如果还有数据的情况下再手动的把原有的fd添加回list_head中,添加方式调用epoll_ctl方法(epoll_ctl的作用对eventpoll的fd实例进行增删改查)修改fd状态为就绪,当程序去做修改时eventpoll会检查是否有fd就绪,这样就会把就绪的fd添加到list_head中

    方案二:

    在ET读取list_head中数据时用循环一次性读完,注意这里不能用阻塞IO去读取会造成死循环,读取不到直接返回相应结果

结论

ET模式避免了LT模式可能出现的惊群现象

ET模式最好结合非阻塞IO读取FD数据,相比LT会复杂一些

lO多路复用-web服务流程

基于epoll模式的web服务的基本流程如图

微信截图_20230214223443

redis原理
网络模型
  • 作者:陌攻(联系作者)
  • 发表时间:2023-02-16 09:16
  • 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)
  • 公众号转载:请在文末添加作者公众号二维码
  • 评论