в узлах.js, почему я должен предпочесть хранилища ключ-значение переменной приложения?


Я разрабатываю приложение реального времени с поддержкой Socket.IO в Node.JS, который будет использоваться парой сотен пользователей одновременно в любой данный момент, и мне нужно сохранить некоторые основные сведения о каждом подключенном клиенте (и удалить эти сведения при отключении клиента).

Я читал, что использование хранилища ключ-значение (такого как Redis) является предпочтительным выбором для хранения таких данных.

Почему хранение данных в обычной переменной in-app (object, например var connectedClientsData = {}) плохо по сравнению с хранение данных в хранилище значений ключей, таком как Redis?

Это только для поддержки масштабирования (например, несколько серверов приложений на основе NodeJS могут подключаться к одному центральному хранилищу ключей и значений), или есть более серьезные недостатки?

3 5

3 ответа:

Есть пара проблем в игре:

1) да, масштабирование. Не только к нескольким серверам, но и к нескольким процессорам через что-то вроде "кластера" (который вы можете найти на npm).

2) В настоящее время V8 имеет ограничения памяти, основанные на его браузерном наследии. Они в какой-то степени поддаются настройке и более тщательно удаляются в следующей версии V8, но это все еще нужно учитывать.

Кроме того, вы гораздо чаще перезапускаете процесс узла (чтобы обновить приложение), чем вы должны перезапустить redis, тем самым потеряв все сеансы.

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

  • Централизация данных - ваши данные хранятся и доступны из центрального места, где не только ваше основное приложение, но и другие приложения могут получить к ним доступ и управлять ими. с этими данными. Например, если вам нужно разделить состояние/данные между двумя системами, гораздо проще сделать это с помощью KV store, выделенного для этой цели.

  • Выгрузка основного приложения - при использовании KV store вы выгружаете основное приложение, что может повысить его производительность и значительно снизить потребление памяти. Тогда масштабирование вашего основного приложения может быть намного проще.

  • Масштабируемость магазина KV - Многие магазины KV имеют встроенный возможности масштабирования, которые в противном случае было бы сложнее реализовать в главном приложении (например, совместное использование состояния между несколькими экземплярами приложения). Эта функциональность также тщательно протестирована и хорошо документирована, так что вам не нужно беспокоиться об этих вещах.

Говорят, что хранилища ключ-значение лучше подходят для храненияпостоянных данных по сравнению с реляционными базами данных, а не с несуществующими объектами в памяти.

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

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

var storage = new Storage();
storage.registerClientDisconnection("client_id_1");

Тогда ваш Storage.registerClientDisconnection() может быть либо

Storage.proptotype.registerClientDisconnection = function(clientId) {
    this.info[clientId].connected = false;
};

Или

Storage.proptotype.registerClientDisconnection = function(clientId) {
    var client = redis.createClient();
    client.set("clientId:"+clientId+":connected", false);
};

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