异步数据库库是如何实现的?

How are asynchronous DB libraries implemented?

一般来说,围绕异步处理请求(play、akka、netty 等)的反应式异步代码有大量炒作。 在以这种方式执行代码时,建议您不要阻塞并尽可能使用异步库。 如果我理解正确的话,这种方式不是为每个请求创建一个线程,而是最终让线程执行器为这些库带来的多个执行部分(请求的主要处理、服务执行器的异步调用、异步 DB 驱动程序执行器等)。 )

这种方式的执行最终分为多个线程(=多个执行程序)。 这些异步库是如何实现的,以便带来任何好处?因为在异步数据库驱动程序具有运行线程的执行程序的情况下,该线程只是等待数据库回答,所以我认为它不会带来任何好处。我们最终会等待,而仅仅通过创建额外的线程来进行等待并没有任何帮助。或者是吗?

我认为对异步库的常见误解是因为想象它们如何工作的最简单方法是考虑如何使用可用的工具以编写库的语言来实现它们到那种语言 - 这通常会导致思考 "if DoWorkAsync has to wait for something else to finish, then surely DoWorkAsync will just be occupying a thread until the work is done"。这听起来很浪费,而且唯一的好处是异步库处理管理将用于等待工作的线程。

但是,与您在 Java 中直接访问的通信方式相比,这些异步方法实际上适用于较低级别的通信形式。

当异步工作必须处理无法立即从中获取数据的某种形式的 IO 时(包括各种各样的事情,例如 IPC、磁盘访问和网络访问 - 等等,通过扩展,数据库调用) OS 将与一个设备驱动程序对话,该设备驱动程序具有对异步调用的内置低级支持,这样它就可以开始工作,然后触发某种中断来告诉 OS 当工作完成时。在此期间,不需要托管线程继续存在(并继续吸取资源)——在设备驱动程序处理工作的同时,不需要有线程等待它。当设备驱动程序指示其异步工作已完成时,OS 向上传递此信息,并将使用一个线程来继续工作。

以上是一个非常简化的解释(并且可能在各种方面都不准确)但希望它能说明问题 - 线程不需要等待异步数据,这回答了你原来的问题。

这篇优秀(简洁)的文章提供了更多信息:There Is No Thread(它是关于 .net 的,但适用相同的原则)

我可以根据我编写 https://github.com/jasync-sql/jasync-sql 的经验告诉你,这是一个异步 mysql 驱动程序,它在后台使用 netty。
首先,当您对数据库执行 sql 查询时,没有线程阻塞。相反,netty 使用事件循环和 java nio 让一个线程在不阻塞的情况下侦听多个套接字。
如果您想了解有关事件循环的一般信息,这是一个非常好的视频:https://www.youtube.com/watch?v=8aGhZQkoFbQ

据我了解,在理想的应用程序中,线程数与内核数相同,它们永远不会阻塞 io,只会执行 CPU 工作(计算)。因此,在那个理想的世界中,您将对所有内容使用 ForkJoinPool。在真实场景中,我从未见过这样做的应用程序,也许只有超调服务。相反,您通常在某些池中有更多线程,但它们通常等待工作并且不应阻塞。这个还能有很好的利用。