В памяти реляционная база данных

Я знаю, что этот вопрос задается несколько раз в stackru. Я отправляю этот вопрос, чтобы узнать, что будет лучшим выбором для моего дизайна. У меня есть следующая схема для моей работы детали.

_unique_key        varchar(256) NULL
_job_handle        varchar(256) NULL
_data              varchar(1024) NULL
_user_id           int(11) NULL
_server_ip         varchar(39) NULL
_app_version       varchar(256) NULL
_state             int(11) NULL
_is_set_stopped    bool

Какую операцию мы делаем на этом столе:

  1. Для каждой работы у нас будет одно обновление и 10 запросов на выборку в этой таблице. Поэтому нам нужна высокая частота для чтения и записи.
  2. Есть много приложений, которые управляют этой таблицей, выполняя фильтр на:
    1. _unique_key
    2. _государство
    3. is_set_stopped
    4. _Идентификатор пользователя
  3. Размер поля _data варьируется от 5 КБ до 1 МБ в зависимости от типа приложения и пользователя.
  4. Приложение может обновить выборочный атрибут.

Решение мы подумали:

MySQL InnoDB

Я думаю, что MySQL не будет достаточно масштабируемым из-за высокого уровня чтения и записи.

MySQL в таблице памяти

Проблема с этим решением заключается в том, что

  1. Он не поддерживает динамический размер поля. Таблицы MEMORY используют формат хранения строк фиксированной длины. Типы переменной длины, такие как VARCHAR, хранятся с использованием фиксированной длины. Источник http://dev.mysql.com/doc/refman/5.0/en/memory-storage-engine.html
  2. выберите для.... обновить, он заблокирует всю таблицу. Я не знаю, будет ли это проблемой.

Redis

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

  1. Он поддерживает только очень большой набор типов данных. Я могу хранить только строку в списке. Мне нужно хранить поля в формате JSON или в другом формате.
  2. Если клиенты хотят обновить определенный атрибут, им необходимо загрузить полное значение, а затем выполнить анализ объекта и выполнить повторную загрузку на сервер. Может быть, я ошибаюсь, есть ли способ сделать это?
  3. Фильтрация по значению будет невозможна. Может быть, я ошибаюсь, есть ли способ сделать это?

MySQL InnoDB в файловой системе TMPFS

Это выглядит многообещающе. Но не стоит так масштабироваться, как Redis или MySQL в таблице памяти.

2 ответа

Решение

В этом вопросе вы путаете грубую производительность (т.е. эффективность) с масштабируемостью. Это разные понятия.

Между InnoDB и механизмами памяти InnoDB, вероятно, будет наиболее масштабируемым. InnoDB поддерживает управление несколькими версиями параллелизма, имеет множество оптимизаций для борьбы с конфликтами, поэтому он будет обрабатывать параллельные обращения гораздо лучше, чем механизм памяти. Даже если это может быть медленнее в некоторых ситуациях, связанных с вводом / выводом.

Redis - это однопоточный сервер. Все операции сериализуются. Он имеет нулевую масштабируемость. Это не значит, что это неэффективно. Напротив, он, вероятно, будет поддерживать больше соединений, чем MySQL (из-за цикла событий на основе epoll), и больший трафик (из-за его очень эффективной реализации без блокировок и структур данных в памяти).

Чтобы ответить на ваш вопрос, я бы попробовал MySQL с InnoDB. Если он настроен правильно (без синхронной фиксации, достаточно буфера кеша и т. Д.), Он может поддерживать хорошую пропускную способность. И вместо того, чтобы запускать его поверх tmpfs, я бы рассмотрел оборудование SSD.

Теперь, если вы предпочитаете использовать Redis (кстати, это не реляционный магазин), вы, безусловно, можете это сделать. Нет необходимости систематически сериализовывать / десериализовывать ваши данные. И фильтрация действительно возможна, если вы можете предвидеть все пути доступа и найти адаптированную структуру данных.

Например:

  • один хэш-объект на задание. Ключ _unique_key. Поля хэша должны соответствовать столбцам вашей реляционной таблицы.
  • один набор на значение состояния
  • 2 комплекта для is_set_stopped
  • один набор на значение идентификатора пользователя

Для каждой вставки работы вам нужно передать следующие команды:

HMSET job:AAA job_handle BBB data CCC user_id DDD server_ip EEE app_version FFF state GGG is_set_stopped HHH
SADD state:GGG AAA
SADD is_set_stopped:HHH AAA
SADD user_id:DDD AAA

Вы можете легко обновить любое поле индивидуально, если вы поддерживаете соответствующие наборы.

Вы можете выполнять фильтрацию запросов, пересекая множества. Например:

SINTER is_set_stopped:HHH state:GGG

С Redis узким местом, скорее всего, будет сеть, особенно если поле данных большое. Я надеюсь, что у вас будет больше рабочих мест на 5 КБ, чем на 1 МБ. Например, 1000 записей / с 1 МБ объектов представляют 8 Гбит / с, вероятно, больше, чем может выдержать ваша сеть. Это верно как для Redis, так и для MySQL.

Я предлагаю postgresql, он более функциональный (имеет больше возможностей и лучшую поддержку сложных запросов и типов данных), чем mysql, и имеет множество параметров настройки.

Если вы дадите postgresql достаточно памяти и правильно настроите параметры, он все кеширует в памяти.

В качестве альтернативы вы также можете использовать его на tmpfs, если вы предпочитаете это, и использовать потоковую репликацию в базу данных на диске для печатного экземпляра.

Потоковая репликация имеет 3 режима работы: асинхронный, при получении и при fsync. Если вы используете первый, асинхронный, вам не нужно ждать синхронизации с диском на сервере репликации, поэтому любые обновления будут очень быстрыми с tmpfs.

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

Независимо от используемой базы данных:

Вы утверждаете, что _data - это varchar[1024], но вы говорите, что он содержит от 5K до 1M данных? Это на самом деле капля? Даже если это было ошибкой длины, mysql не поддерживает поля varchar длиннее 65535 байт! Я полагаю, что это не так сильно обновляется, как другие строки, возможно, было бы разумно разделить это на две таблицы, одну со статическими данными и одну с динамическими данными, чтобы минимизировать доступ к диску.

Другие вопросы по тегам