Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/42.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js 使用异步i/o编写数据库_Node.js_Database_Libuv - Fatal编程技术网

Node.js 使用异步i/o编写数据库

Node.js 使用异步i/o编写数据库,node.js,database,libuv,Node.js,Database,Libuv,我最近遇到了一个低级库,它可以让NodeJ发挥异步的魔力。这让我思考。我想澄清以下几点: Nodejs具有异步i/o调用。然而,如果我调用一个(远程)数据库的API,对db的实际读/写将是同步的,但节点不必等待。是否有可能使数据库本身以异步方式写入磁盘?是否有使用libuv进行实际异步i/o的数据库 Javascript以单线程著称。我知道nodejs运行时不需要这样-如果我有4个cpu核,我可以启动4个实例。但是,如果我使用libuv用一种支持线程的语言编写另一个web框架,它不具备异步I/o

我最近遇到了一个低级库,它可以让NodeJ发挥异步的魔力。这让我思考。我想澄清以下几点:

  • Nodejs具有异步i/o调用。然而,如果我调用一个(远程)数据库的API,对db的实际读/写将是同步的,但节点不必等待。是否有可能使数据库本身以异步方式写入磁盘?是否有使用libuv进行实际异步i/o的数据库

  • Javascript以单线程著称。我知道nodejs运行时不需要这样-如果我有4个cpu核,我可以启动4个实例。但是,如果我使用libuv用一种支持线程的语言编写另一个web框架,它不具备异步I/o和多线程的所有优点吗?这样的事情已经存在了吗


  • 你混淆了两个概念。在对服务执行查询时,您可以异步等待(通过epoll/kpoll/libuv…)这一事实并不意味着您的查询在另一端是非阻塞的,反之亦然。这也并不意味着,在事件循环中,事情“感觉”是异步的,而实际上是异步的

    让我们回到什么是事件循环,以及nodeJS是如何发挥其魔力的。我觉得这是一个好的开始

    事件循环的可见部分是代码编写方式的变化——从大部分同步到大部分异步。不可见的部分是,这个异步代码被尽可能多地抛出到事件循环中,在后台检查要做的事情—IO、计时器等。这不是一个新想法,它的工作(提供并发性)做得非常好

    libuv的文档实际上对此非常有描述性。是对他们所做设计选择的描述,从中得出以下流程图:

    请注意,他们没有声明他们已经实现了真正的异步——因为他们没有。底层系统调用保持同步。只是感觉不是这样。这是关键

    关于数据库上的磁盘I/O,我不久前在海牙做过一次演讲,坦率地说,大多数关键I/O都是阻塞。例如,您不能说“嘿,我要更新磁盘快照,同时只追加txlog!”——因为如果其中一个失败,您就有一个严重的回滚问题,可能还有未知状态

    关于问题2,我会给出代码示例,但我不确定您熟悉哪些语言。底线是,当某物越过线程边界时,它就变成了地狱。一个非常简单的例子是这样的-假设您的事件循环有两个计时器,如下所示:

    • 定时器1每0.5s触发一次,增加给定的状态变量
      a
    • 定时器2,每当有人提供用户输入时触发,将状态变量除以2
    假设您在一个线程上运行。即使您的事件循环感觉是异步的,但它是完全连续的-当计时器2运行时,计时器1永远不会运行

    现在添加第二个线程,使计时器2从中运行。如果没有一个卫兵到位,很有可能在某个地方发生严重的错误

    为了能够以简单的方式将某个变量除以2(而不利用专门用于此类内容的CPU指令),必须检索变量,将其除以2,然后将其放回内存中

    同样,递增也是一个三阶段的过程(同样,采用天真的方法)

    一旦这两个计时器发生冲突,您可能会遇到以下疯狂的比赛情况:

    THREAD 1          | THREAD 2
       <- A=1         |
     Local:A=1+1=2    |  <- A=1
                      |  Local: A=1*2=2
         A=2 ->       |  A=2 ->
    
    螺纹1 |螺纹2
    
    线程2在线程1计算的中途开始运行,检索到错误的状态变量值(因为线程1尚未更新变量),并将其乘以2。你应该有3个,但事实上你最终只有2个

    为了防止这种情况,有很多方法和工具。现在大多数处理器架构都有原子指令(例如),开发人员如果知道在哪里需要它们,就可以利用这些指令。在这些工具之上,您可以有一整套工具—互斥锁、读/写锁、信号量等等。。。以降低或消除这些问题的成本,并在您知道需要它们的地方时


    不用说,概括这一点绝非易事。

    感谢您抽出时间键入描述性答案。“大多数重要的I/O都是阻塞的”-因此,如果我有一种并发处理的方法并确保事务处理正常,那么数据库读/写就不需要阻塞,对吗?是的,我知道在文件系统级别,一切都会阻塞。我只是好奇,如果我编写一个单线程的db,但使用一个事件循环,会发生什么。这意味着我可以“执行”一个非常耗时的
    SELECT
    ,而不必等待响应,然后执行一个
    INSERT
    ,前提是我有正确的锁。@lonesword“blocking”是一个大字。很难提供一个通用的答案,因为即使在linux上纯读/写操作的世界中,人们也可以访问
    select
    /
    pselect
    ,以查看多个文件描述符。然而,对于大多数RDBMS解决方案,读/写并不是阻塞的。现在我真希望有人能录下我的演讲,我深入探讨了很多数据库解决方案的所有事务机制。“然而,对于大多数RDBMS解决方案,读/写都没有阻塞”-这对我来说是新闻。如果你能抽出时间在博客上发表演讲,我很乐意阅读。谢谢您的时间。@lonesword他们在查询级别没有阻塞。它们在I/O级别阻塞很短的时间(通常写入AOL)。这就是我一直试图提出的观点——“阻塞”这个词太笼统了。如何阻止?在什么级别?影响谁?例如,在MySQL的情况下