Вопрос по node.js, cluster-computing, javascript, static, interprocess – В node.js как объявить общую переменную, которая может быть инициализирована главным процессом и доступна рабочим процессам?

18

Я хочу следующее

During startup, the master process loads a large table from file and saves it into a shared variable. The table has 9 columns and 12 million rows, 432MB in size. The worker processes run HTTP server, accepting real-time queries against the large table.

Вот мой код, который явно не достигает моей цели.

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.

Являетсяmemcached подходящий выбор для этих данных? sarnold
Если ваш набор растет, вы можете пересмотреть оптимизацию структуры данных или запрос программного обеспечения базы данных. Кроме того, Node.js был бы ужасным выбором языка для системы баз данных, в то время как ваша программа на C ++ могла бы быть достаточно хорошей. Shane Hsu

Ваш Ответ

5   ответов
6

node.js просто не поддерживает, Вы должны искать альтернативы, такие какзапрос к базе данных или используяMemcached.

Почти 4 года спустя .. @Martin Blech я получилquestion for you!
Существует очень много модулей node.js npm, и некоторые из них поддерживают совместную память, например,npmjs.org/search?q=shared+memory
VOTE HERE: github.com/nodejs/help/issues/560 , Это потому, что никто не голосует за то, чтобы этоstill еще реализовано.
3

Redis - это открытый исходный код, лицензия BSD, расширенный кэш и хранилище значений ключей. Его часто называют сервером структуры данных, поскольку ключи могут содержать строки, хэши, списки, наборы, отсортированные наборы, растровые изображения и гиперлоглоги.

redis.io

Да, это работает отлично. Вы можете получить данные из Redis в любом месте (коды блоков узлов), которые вам нужны.
Ноно, я имею в виду, вам не нужно делатьcopy? Если вы это сделаете, то это больше не правда общая память.
Это даже сработает? .. Вам не нужно передавать данные из Redis в Node, эффективно преодолевая цель совместной памяти?
5

попробуйтемой собственный модуль общей памяти, Оно используетmmap таким образом, данные загружаются по мере их доступа, а не сразу. Память распределяется между всеми процессами на машине. Использовать его очень просто:

const Shared = require('mmap-object')

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

console.log(shared_object.property)

Это дает вам обычный объектный интерфейс к хранилищу значений ключей или строк. Это очень быстро в моих приложениях.

Также естьэкспериментальная версия модуля для чтения и записи доступны для тестирования.

A contributor добавлены биты, чтобы компилировать его под MSVS некоторое время назад. Я недавно не тестировал его и не имею удобного доступа к среде сборки Windows.
Это нормально работает на Windows?
4

как в C ++. Он не копирует текущее состояние процесса, он запускает новый процесс. Таким образом, в этом случае переменные не являются общими. Каждая строка кода работает для каждого процесса, но в главном процессе флаг cluster.isMaster установлен в значение true. Вам нужно загрузить свои данные для каждого рабочего процесса. Будьте осторожны, если ваши данные действительно огромны, потому что каждый процесс будет иметь свою собственную копию. Я думаю, вам нужно запросить части данных, как только они вам понадобятся, или подождать, если вам действительно понадобится все это в памяти.

12

вам нужно поделиться данными объекта MASTER с объектом WORKER. Это можно сделать очень легко, используя события:

From Master to worker:

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

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

From Worker to Master:

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

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

Я надеюсь, что таким образом вы можете отправлять и получать данные в двух направлениях. Пожалуйста, пометьте его как ответ, если вы найдете его полезным, чтобы другие пользователи также могли найти ответ. Спасибо

Спрашивающий спрашивает о «больших данных с миллионами строк». Ваш ответ может не сработать здесь.
хорошо @de Раад, что бы ты посоветовал для этого?
Это не «совместно используемая переменная», это совершенно новая копия данных, уже сохраненных в памяти, что лишает возможности доступа к тому же местоположению в памяти от другого работника. Различие имеет важные последствия для того, сколько оперативной памяти вам нужно. Кроме того, это ужасно неэффективно, поскольку данные проходят через методы JSON.parse () и JSON.stringify (), которые блокируют цикл обработки событий ...
Я считаю, что информация актуальна. Если запрос выполняется в главном процессе, он будет отправлять только соответствующие данные, намного меньше, чем полный набор данных. Это может работать через IPC. Эти данные в любом случае необходимо будет отправлять через HTTP, IPC не станет узким местом. Предложение других баз данных является странным, поскольку совершенно ясно, что OP описывает master как систему баз данных.
@MupparthyRavindranath ... Мой ответ объясняет, как можно обмениваться данными между мастером и рабочим процессом. Если проблема связана с БД, то спрашивающий должен постараться максимально ее нормализовать, или спрашивающий должен разделить структуру операторов запроса / БД, чтобы мы могли найти решение в этом направлении.

Похожие вопросы