在node.js中,如何声明一个可由主进程初始化并由工作进程访问的共享变量?

时间:2012-06-09 23:02:29

标签: javascript node.js static cluster-computing interprocess

我想要以下

  • 在启动期间,主进程从文件加载大表并将其保存到共享变量中。该表有9列和1200万行,大小为432MB。
  • 工作进程运行HTTP服务器,接受针对大表的实时查询。

这是我的代码,显然无法实现我的目标。

var my_shared_var;
var cluster = require('cluster');
var numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
  // Load a large table from file and save it into my_shared_var,
  // hoping the worker processes can access to this shared variable,
  // so that the worker processes do not need to reload the table from file.
  // The loading typically takes 15 seconds.
  my_shared_var = load('path_to_my_large_table');

  // Fork worker processes
  for (var i = 0; i < numCPUs; i++) {
    cluster.fork();
  }
} else {
  // The following line of code actually outputs "undefined".
  // It seems each process has its own copy of my_shared_var.
  console.log(my_shared_var);

  // Then perform query against my_shared_var.
  // The query should be performed by worker processes,
  // otherwise the master process will become bottleneck
  var result = query(my_shared_var);
}

我尝试将大表保存到MongoDB中,以便每个进程都可以轻松访问数据。但是表大小非常大,即使使用索引,MongoDB也需要大约10秒才能完成查询。这太慢了,我的实时应用程序无法接受。我也试过Redis,它在内存中保存数据。但Redis是一个键值存储,我的数据是一个表。我还写了一个C ++程序来将数据加载到内存中,查询花了不到1秒钟,所以我想在node.js中模拟它。

5 个答案:

答案 0 :(得分:12)

如果我用几句话翻译您的问题,您需要与WORKER实体共享MASTER实体的数据。使用事件可以非常轻松地完成:

从大师到工作人员:

worker.send({json data});    // In Master part

process.on('message', yourCallbackFunc(jsonData));    // In Worker part

从工人到主人:

process.send({json data});   // In Worker part

worker.on('message', yourCallbackFunc(jsonData));    // In Master part

我希望通过这种方式您可以双向发送和接收数据。如果您发现它有用,请将其标记为答案,以便其他用户也可以找到答案。感谢

答案 1 :(得分:6)

您正在寻找共享内存,node.js just does not support。您应该寻找替代方案,例如querying a database或使用memcached

答案 2 :(得分:5)

如果对您的应用程序进行只读访问,请尝试my own shared memory module。它在封面下使用mmap,因此数据在访问时加载,而不是一次性加载。内存在机器上的所有进程之间共享。使用它非常简单:

const Shared = require('mmap-object')

const shared_object = new Shared.Open('table_file')

console.log(shared_object.property)

它为您提供了一个到字符串或数字的键值存储的常规对象接口。它在我的应用程序中超级快。

还有experimental read-write version of the module可用于测试。

答案 3 :(得分:4)

在node.js中,fork与C ++不同。它不是复制当前的进程状态,而是运行新进程。因此,在这种情况下,不共享变量。每行代码都适用于每个进程,但主进程将cluster.isMaster标志设置为true。您需要为每个工作进程加载数据。如果您的数据非常庞大,请小心,因为每个进程都有自己的副本。我认为您需要在需要时立即查询部分数据,或等待您真正需要在内存中使用数据。

答案 4 :(得分:3)

您可以使用Redis。

Redis是一个开源的,BSD许可的高级键值缓存和存储。它通常被称为数据结构服务器,因为密钥可以包含字符串,散列,列表,集合,有序集,位图和超级日志。

redis.io