由redis源码epoll和serverCron引发的同步异步问题

最近看redis源码,对网络处理模型,命令接收这一块非常困惑,发现对同步/异步,阻塞/非阻塞这边概念模棱两可。

先放问题:
在看到serverCron时,源码中注释写到:
This is our timer interrupt, called server.hz times per second.Here is where we do a number of things that need to be done asynchronously.
For instance: …
这是redis的时间中断器,每秒调用server.hz次,以下是需要异步执行的操作:清除过期键,更新统计信息等…

Q1:这个时间事件函数,是异步执行的,这个异步是怎么实现的?有没有开线程去执行?
异步和多线程没有任何强的联系,多线程是异步的实现手段之一,可以互相组合使用,因为异步只不过是事件机制而已,事件一定要用到回调。
同步回调就是:把函数b传递给函数a。执行a的时候,回调了b,a要一直等到b执行完才能继续执行;
异步回调就是:把函数b传递给函数a。执行a的时候,回调了b,然后a就继续往后执行,b独自执行。---请注意这里不要和多线程纠缠起来:线程是存在于一个进程里的,而异步回调可能是好几个进程。

作者:二律背反
链接:https://www.zhihu.com/question/47371217/answer/105797161

Q2:redis的IO多路复用程序如ae_pool.c文件封装了epoll函数。epoll是同步的还是异步的?
在处理 IO 的时候,阻塞和非阻塞都是同步 IO。
只有使用了特殊的 API 才是异步 IO。
图片来源--陈硕

为了解决以上问题,先要解决什么是同步异步,什么是阻塞非阻塞,什么又是事件驱动。来源:https://www.zhihu.com/question/19732473

四个概念的一句话概括:
同步/异步:相同/不同的步调,描述两个模块之间的关系。
阻塞/非阻塞:一个模块自身是否被卡主/继续运行下去。

《操作系统概念》原文:
在这里插入图片描述
进程间的通信是通过 send() 和 receive() 两种基本操作完成的。具体如何实现这两种基础操作,存在着不同的设计。
消息的传递有可能是
阻塞的或非阻塞的 – 也被称为同步或异步的:
1)阻塞式发送(blocking send). 发送方进程会被一直阻塞, 直到消息被接受方进程收到。
2)非阻塞式发送(nonblocking send)。 发送方进程调用 send() 后, 立即就可以其他操作。
3)阻塞式接收(blocking receive) 接收方调用 receive() 后一直阻塞, 直到消息到达可用。
4)非阻塞式接受(nonblocking receive) 接收方调用 receive() 函数后, 要么得到一个有效的结果, 要么得到一个空值, 即不会被阻塞。

作者:萧萧
链接:https://www.zhihu.com/question/19732473/answer/241673170

一个网络包从A到B的流程:
1.从A的业务代码到A的软件框架
2.从A的软件框架到计算机的操作系统内核
3.从A所在计算机的内核到网卡
4.从网卡经过网线发到交换机等设备,层层转发,到达B所在计算机的网卡
5.从B所在计算机的网卡到B所在计算机的内核
6.从B所在计算机的内核到B的程序的用户空间
7.从B的软件框架到B的业务代码

这个层级关系就像是过程调用一样,前一级调用后一级的功能,后一级返回一个结果给前一级(比如:成功,或者失败)。
只有在单独一级的调用上,可以说同步还是异步的问题。所谓同步,是指调用协议中结果在调用完成时返回,这样调用的过程中参与双方都处于一个状态同步的过程。而异步,是指调用方发出请求就立即返回,请求甚至可能还没到达接收方,比如说放到了某个缓冲区中,等待对方取走或者第三方转交;而结果,则通过接收方主动推送,或调用方轮询来得到

从这个定义中,我们看,首先1和7,这取决于软件框架的设计,如果软件框架可以beginXXX,然后立即返回,这就是一种异步调用,再比如javascript当中的异步HTTP调用,传入参数时提供一个回调函数,回调函数在完成时调用,再比如协程模型,调用接口后马上切换到其他协程继续执行,在完成时由框架切换回到协程中,这都是典型的异步接口设计。
而2和6,其实都需要调用方自己把数据在内核和用户空间里搬来搬去,其实都是同步接口(如epoll),除非是IOCP这样的专门的异步传输接口,所以这一级其实是同步的,阻塞与非阻塞的区别其实是影响调用接口的结果(在特定条件下是否提前返回结果),而不是调用方式。
3和5,内核一般通过缓冲区,使用DMI来传输数据,所以这一步又是异步的。
4,以太网是个同步时序逻辑,随信号传输时钟,必须两边设备同时就绪了才能开始传输数据,这又是同步的。总结来说,讨论究竟是异步还是同步,一定要严格说明说的是哪一部分。
说非阻塞是同步而不是异步,这毫无疑问是正确的,然而说某个框架是异步IO的框架,这也是正确的,因为说的其实是框架提供给业务代码的接口是异步的,不管是回调还是协程,比如说我们可以说某个库是异步的HTTPClient,并没有什么问题,因为说的是给业务代码的接口。由于通常异步的框架都需要在2中使用非阻塞的接口,的确会有很多人把非阻塞和异步混为一谈。

猜你喜欢

转载自blog.csdn.net/abyss_miracle/article/details/118797416
今日推荐