0

我已经设置了一个节点服务器来保存日志信息。预计会有非常大量的请求进入。我正在使用 mongo 数据存储,但它的性能太不可靠了。读取事物报告方面的数据通常需要异常长的时间。所以我改用经典的mysql。如果您准备批量插入而不是单例插入,那么显然有显着的写入吞吐量优势。于是我找到了这个人:

https://gist.github.com/3078520

我喜欢它的简单。它只有几行,非常强大。它有两个主要功能add(),将记录添加到队列中,然后flush()在队列达到一定大小时调用。然后它将flush()队列加入一个长字符串并创建一个长的批量插入语句,然后将其发送到 mysql 驱动程序(我从提供的链接简化了函数:

this.flush = function () {
/*1*/    var sql = queryTemplate.replace('{values}', '\n('+ queue.join('),\n(') +')');
/*2*/    handle.query(sql, callback);
/*3*/    queue = [];
}

这本质上是一个类函数,它是请求处理程序拥有的单个类实例的一部分。所以我的问题是,这安全吗?是queue一个类变量。当flush()被调用时,它处理队列。我能看到的唯一问题是如果flush()被调用,则执行第 1 行以生成 sql 语句(只是一个字符串),然后调用add()另一个queuequery(). 在这种情况下,第二个进程添加的记录将丢失,因为第一个进程在创建 sql 语句时不知道它,并且在清除queue. 这可能吗?

这个问题的更一般化的形式如下。一旦一个函数开始执行,其他任何外部因素都会影响其范围之外的变量吗?这是一个非常简单的示例,假设不同的请求调用这两个函数,是否可以在此示例中执行 console.log:

var global_number;
function a(){
  global_number=2;
}
function b(){
  global_number=1;
  if(global_number==2){
    console.log("a() influenced global_number in the middle of b()'s execution")
  }
}

这主要是一个是/否的问题,但我正在寻找更多。一个简短的解释或指向我可以了解更多信息的页面的链接会很棒!谢谢!

4

2 回答 2

1

如果一个函数是同步的,那么在函数开始执行和完成之间,没有任何东西可以影响该函数引用的变量。

但是,如果函数调用异步函数(例如 MySQL 查询),则函数本身是异步的,其他代码可以在函数运行时间和异步函数回调时间之间修改函数的父/全局范围内的变量运行。

于 2012-11-16T18:03:44.433 回答
1

是的,如果函数的执行是异步的,那么您可能会遇到全局变量拥有的数据的问题。这是测试场景;

var globalVariable = 10;

function a ()
{
    var timer = setInterval(function() {
        globalVariable--;
        console.log(globalVariable)
    }, 1000);
}

function b ()
{
    setTimeout(function() {
        globalVariable = 20;
    }, 3000);
}

a();
b();

这将输出:

9
8
7
19
18
17
16

如果你要求函数执行中断不是异步的,没办法!请参阅示例。

var globalVariable = 1000000000;
function a () {
    for(var i=0; i < 1000000000; i++)
    {
        if(globalVariable == 20000) console.log('From a() : ' + globalVariable);
        globalVariable--;
        if(globalVariable == 0) break;
    }
}

function b () {
    setTimeout(function() {
        console.log('From b() : ' + globalVariable);
        globalVariable = 20000;
        console.log('From b() : ' + globalVariable);
    }, 1);
}

b();
a();

这将始终输出:

From a() : 20000
From b() : 0
From b() : 20000

因此,您的问题答案是否定的,您不能中断同步功能的执行。

然而; 在您的代码片段示例中,似乎可以清空,queue因为您已经在第 1 行使用了queuewithqueue.join中的数据。另一方面,这种方法会受到回滚操作的影响。例如,当 sql 返回错误时,您可能无法重新填充queue.

于 2012-11-16T18:12:07.620 回答