Статьи

Hybrid NoSQL: MarkLogic как магазин KV, часть 1

Исходя из моего блога об использовании хранилища документов в качестве хранилища KV, я решил провести несколько простых тестов, чтобы увидеть, как Redis и MarkLogic сравниваются на моей машине…

Спойлерные выводы. Продолжайте читать для деталей:

  • Благодаря ведению журнала и строгой долговечности Redis только в 5 раз быстрее, чем MarkLogic, хранит простые данные с одним ключом.
  • Для немного более сложных наборов данных (хэшей) Redis работает только в 3,5 раза быстрее
  • Если вам нужен какой-либо запрос или возможность поиска, MarkLogic предоставляет это, а Redis — нет.
  • Возможно, вам удастся настроить хранилище документов (MarkLogic) достаточно быстро, чтобы заменить Redis, но вы не можете добавить функциональность в хранилище значений ключей (Redis) для решения всех случаев использования запросов, которые может обрабатывать MarkLogic.
  • Попробуйте использовать только MarkLogic. ; о) (Flamebait!)

Вступление

На данный момент я должен сказать, что я ни в коем случае не эксперт Redis. Я исследовал его для своей книги NoSQL для чайников и сравнил его функциональность с MarkLogic с точки зрения типа данных . Мне нравится Redis . Интересно, насколько близка его скорость к MarkLogic?

Зачем сравнивать их, когда они такие разные? Я иногда сталкиваюсь с компаниями, использующими MongoDB + Redis. Они хранят данные в MongoDB, но их приложение кэширует данные, используя Redis, чтобы обойти ограничения скорости. Очень хороший вариант использования.

BBC использует MarkLogic для хранения метаданных программы, а служба iPlayer кэширует их в Redis. Опять действительный вариант использования — кеширование.

Хотел бы я знать, было ли это всегда необходимо? Можете ли вы перенастроить свое хранилище документов для поддержки тех же самых низкоуровневых функций, что и Redis, и таким образом настроить базу данных документов?

В своем последнем сообщении в блоге я сравнил функциональность и пришел к выводу, что MarkLogic может предоставлять те же функции, что и Redis. Я предположил, что на моем ноутбуке Redis, вероятно, получит до 100000+ операций Set в секунду, тогда как MarkLogic с индексированием по умолчанию будет ближе к 3000 / сек.

Поэтому я решил посмотреть, что происходит по умолчанию …

Настройка

Я использую очень научную настройку AdamsCurrentGenerationLaptop [™]. Это MacBook Pro (Retina, 15-дюймовый, середина 2015 года) с 2,2 ГГц Intel Core i7 и 16 ГБ оперативной памяти.

Моя тестовая система фактически работает в VMWare Fusion 7, на CentOS 6.6 с ядром 2.6.32.

Redis

Я скачал Redis, распаковал дистрибутив, сделал make и sudo make install, а затем запустил его в автономном режиме. Не было внесено никаких изменений в конфигурацию по умолчанию.

Запуск Redis-бенчмарк дал это:

[demouser@localhost src]$ redis-benchmark -q -n 100000 -t set
SET: 114285.71 requests per second

Оказывается, я сделал довольно хорошее предположение в своей последней записи в блоге! Redis может выполнять более 114 000 транзакций SET в секунду на моем виртуальном компьютере, установленном на моем Mac.

Но что на самом деле происходит под капотом? Сохраняются ли они в КИСЛОТНОЙ манере?

Что ж, создатели redis-benchmark делают меня счастливым! Они не создали инструмент для тестирования с множеством настроек, которые делают Redis великолепно выглядящим.

Инструмент использует 50 клиентов по умолчанию, что не является необоснованным числом. Конвейерная обработка отключена — это означает, что изменения подтверждаются до следующей команды. Таким образом, вы знаете, что данные соответствуют следующей команде. (Включение конвейерной передачи должно увеличить производительность SET до более 400 КБ, но это не очень надежно для большинства реальных приложений, IMHO).

Немного капризно то, что инструмент обращается к одному и тому же ключу. Тск тск. Имитация загрузки с чистой записью с 10% обновлений (т.е. 90% случайных ключей) дает вам следующее: —

[demouser@localhost src]$ redis-benchmark -q -n 100000 -r 90000 -t set
SET: 115740.73 requests per second

Это на самом деле быстрее! Запуск его еще несколько раз давал мне от 109 до 115 тысяч операций в секунду. Так что это примерно эквивалентно. Так что команда Redis-Benchmark права — это довольно разумный инструмент для оценки нагрузки.

Но подождите, AOF и fsync вызываются для обеспечения долговечности? Нет, не по умолчанию. Я бы лучше добавил их, чтобы создать справедливое сравнение с ACID-совместимой базой данных, такой как MarkLogic…

Настройка AOF и fsync

Изменения в журналах MarkLogic. Все изменения журнала записываются на диск, и эти изменения применяются к сохраненным данным позже (обновления происходят в ОЗУ, как и в Redis, при этом журнал используется в случае сбоя). Журналирование — это то, как большинство современных баз данных обеспечивают хорошую пропускную способность записи, обеспечивая при этом целостность и долговечность данных. Мы хотим настроить Redis так, чтобы мы сравнивали яблоки и яблоки …

В: Это честный тест?

A: Возможно. Если вы рассматриваете Redis для всех ваших потребностей хранения данных, то это определенно справедливо. Поскольку этот пост посвящен использованию хранилища документов для ваших нужд KV, нам необходимо сравнить обе базы данных в «золотом хранилище», где Redis может быть основным источником этих данных, а не просто кешем. Так что для наших нужд (без потери данных) это справедливый тест.

Изменение конфигурации Redis с помощью следующих параметров делает то, что нам нужно:

appendfsync always
appendonly yes

Первая настройка гарантирует, что для каждой записи журнал AOF добавляется на диск. Включение AOF означает, что мы записываем только файл AOF (журнал), а не изменяем все данные на диске.

Сохранение этой конфигурации и выполнение наших операций снова дает нам: —

[demouser@localhost redis-3.0.3]$ redis-benchmark -q -n 100000 -t set -r 90000
SET: 44642.86 requests per second

Это составляет 38,57% от числа операций записи в секунду. Я думаю, что это, вероятно, точно — нет способа записи данных на диск — это медленнее, чем ОЗУ. Если вам абсолютно необходимо писать долговечность, то вы должны заплатить цену.

И все же это чертовски впечатляющее число! (Молодцы инженеры Redis, кстати, +1 пива к вам.)

Использование AOF — это хороший способ обеспечить быструю запись при использовании журналирования. AOF означает добавление только файла — поэтому вы добавляете изменения в файл, который в дальнейшем будет объединен. Обсуждение этого выходит за рамки этого сообщения в блоге, хотя …

Другие заметки Redis

Следует отметить, что один экземпляр Redis работает с использованием одного ядра. Таким образом, я тестирую 1 ядро ​​моего любимого Mac, а не всю машину. Позже я буду устанавливать MarkLogic с одним лесом. При этом используется 1 ядро ​​для управления всеми записями на стенде. Это обеспечивает хорошее сравнение на низком уровне, поэтому я сохранил Redis только с 1 ядром.

Следует отметить, что запросы на чтение в MarkLogic могут использовать другое ядро, а не 1 Redis, которым он ограничен. Поскольку я в основном говорю о скорости записи, я не слишком обеспокоен. Стоит отметить, что в случае, если вы увидите какие-либо показатели производительности тростника в другом месте.

MarkLogic Server

Я использую MarkLogic Server 7.0-5.2. Почему не версия 8? Ну, потому что я тупо начал делать эти тесты на неправильном образе VMware. Oopsie. Не могу позволить себе время обновить и перепроверить всю мою работу, поэтому V7 придется делать.

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

Поскольку эта машина используется для большой работы, я отключил все остальные леса (части баз данных, похожие на осколки), чтобы обеспечить реальное сравнение. MarkLogic может содержать несколько баз данных на одну машину.

Это оставляет меня с базой данных документов — одна используется для тестирования — с одним лесом и, следовательно, одним ядром в использовании. Существуют и другие внутренние базы данных, такие как «Безопасность» и «Модули», но они необходимы, поэтому их отключение не требуется. Пока я оставил индексы по умолчанию на месте, чтобы вы получили реалистичное число. MarkLogic выполняет большую индексацию данных, добавленных к нему, поэтому производительность снижается. Вы получаете выгоду от этого во время сложных запросов, которые выполняются намного быстрее.

Я использую MLCP (MarkLogic Content Pump — мы знаем ненормальное имя) для загрузки 100 000 очень маленьких XML-документов на сервер. У них есть один элемент: <data> что-то </ data>.

mlcp.sh import -host localhost -port 7777 -username admin -password admin -input_file_path /home/demouser/mldata/simple/ -mode local -input_file_pattern '.*\.xml'
...
15/09/07 06:50:37 INFO contentpump.LocalJobRunner: completed 100%
15/09/07 06:50:37 INFO contentpump.LocalJobRunner: com.marklogic.contentpump.ContentPumpStats: 
15/09/07 06:50:37 INFO contentpump.LocalJobRunner: ATTEMPTED_INPUT_RECORD_COUNT: 100000
15/09/07 06:50:37 INFO contentpump.LocalJobRunner: SKIPPED_INPUT_RECORD_COUNT: 0
15/09/07 06:50:37 INFO contentpump.LocalJobRunner: Total execution time: 245 sec

Это дает результат 408 документов в секунду. Который естественно отстой.

ОДНАКО mlcp сообщает о времени неправильно. Он сообщает время выполнения, которое включает в себя 2 минуты, которые требуются, чтобы разобраться в жизни файловой системы. Фактическое время приема составило 109 секунд, что дает 917,43 документов в секунду. Я буду использовать это, как в реальном приложении, у вас не будет накладных расходов на обработку MLCP.

Это использует параметры по умолчанию batch_size 100 и thread_count 4, хотя. Изменение количества потоков до 50, очистка БД и повторная попытка приводит к: —

15/09/07 07:20:01 INFO contentpump.LocalJobRunner: completed 100%
15/09/07 07:20:03 INFO contentpump.LocalJobRunner: com.marklogic.contentpump.ContentPumpStats: 
15/09/07 07:20:03 INFO contentpump.LocalJobRunner: ATTEMPTED_INPUT_RECORD_COUNT: 100000
15/09/07 07:20:03 INFO contentpump.LocalJobRunner: SKIPPED_INPUT_RECORD_COUNT: 0
15/09/07 07:20:03 INFO contentpump.LocalJobRunner: Total execution time: 215 sec

Опять ложь. На самом деле это заняло 94 секунды, что дает 1063,83 документа / секунду.

Одна вещь, которую я еще не изменил — хотя мое число клиентов установлено на 50, количество потоков на сервере приложений MarkLogic XCC (MLCP использует XDBC для хранения данных) ограничено 32. Изменение этого значения до 64 приводит к точно та же производительность, хотя. Я предполагаю, что мои запросы настолько малы, что изменение этого параметра не сильно изменилось.

Эта скорость в 44 раза медленнее, чем у Redis. Этого и следовало ожидать. MarkLogic много занимается индексацией. Итак, давайте отключим как можно больше индексов …

При этом сценарии без индексов общее время, затрачиваемое на обработку, составило 95 секунд, незначительное улучшение привело к 1052,63 документов в секунду.

Предупреждение: я думаю, что я достиг предела CPU … Я тупо установил свой образ VMware, чтобы иметь 1 ядро. Я перезапускаю его с двумя ядрами и загружаю данные с хоста (OS X), а не с образа VMware. (Я сделаю то же самое снова для Redis). Я также предполагаю, что ядро ​​VMWare на самом деле является аппаратным потоком, поэтому я дам ему 4 потока (2 физических ядра). Результаты моих тестов сейчас: —

Redis (с AOF и fsync, 100% новые ключи):

adamfowbookwork:src adamfowler$ ./redis-benchmark -h 192.168.123.4 -n 100000 -r 100000 -t set -c 50
====== SET ======
 100000 requests completed in 4.69 seconds
 50 parallel clients
 3 bytes payload
 keep alive: 1

0.00% <= 1 milliseconds
8.46% <= 2 milliseconds
99.26% <= 3 milliseconds
99.85% <= 4 milliseconds
99.98% <= 5 milliseconds
100.00% <= 5 milliseconds
21312.87 requests per second

MarkLogic (без индексов, без повторного использования ключа): 24 секунды! Скорость 4166,66 документов добавляется в секунду.

Как вы можете видеть, оба страдают от отсутствия локального хоста и необходимости проходить через сети VMWare, но это лучше, чем проблемы узких мест ЦП. В производительности MarkLogic произошли значительные изменения. Это в основном связано с узким местом процессора. MarkLogic использует несколько потоков в ядре, включая накладные расходы на поддержание безопасности и базы данных модулей. MLCP также высасывает подобное из процессора благодаря обработке потоков Java. Как только я добавил больше ядер, эти накладные расходы были удалены. Также по какой-то причине операции ввода-вывода при чтении дисков, похоже, страдали в гостевой ОС CentOS, поэтому запуск MLCP с моего хоста значительно улучшил производительность.

Теперь вы видите, что с транзакционной целостностью MarkLogic всего в 5 раз медленнее, чем Redis, для простого хранения ключей! Совершенное достижение.

Теперь, повторно включив индексы, чтобы получить лучшее представление о снижении производительности при загрузке, тест MLCP занял 29 секунд, что привело к увеличению пропускной способности 3448,28 в секунду. Это скорость, которую я ожидал от моего предыдущего поста в блоге!

(Я мог бы включить режим «быстрой загрузки» в MLCP, который обходит диспетчер транзакций, но это было бы мошенничеством для этого теста! Я подумал, что упомяну об этом на случай, если он вам когда-нибудь понадобится.)

сводные показатели

Одна вещь, которую я хочу упомянуть, это то, что в хранилище документов обычно объединяется связанная информация. Поэтому вместо того, чтобы изменять отдельные ключи, вы обновляете структуры данных. В хранилище KV это хеши, тогда как в хранилище документов это документы. Таким образом, вы можете добавить 10 вышеуказанных ключей в один документ и обновить их вместе.

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

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

Ах … Похоже, инструмент Redis Benchmark не поддерживает команды HSET или HMSET … Черт … Мне придется искать в другом месте …

Интересно, что кто-то еще пытался сравнить производительность строк Redis с хэшами в слое ORM. Это можно найти в этой статье блога .

Это показывает для записи десяти элементов, что HMSET (настройка нескольких ключей в одном обращении, что-то вроде сохранения документа) было в 3,59 раза быстрее для каждого элемента — чем сохранение 1 ключа (который может быть документом или агрегатом) с помощью SET. Я буду использовать это в качестве сравнения.

«За элемент» означает «стоимость», а не «совокупность», поэтому необходимо некоторое разделение скоростей…

Это означает, что фактическая скорость Redis для 10-элементного документа, сохраняемого с использованием хэшей, будет равна скорости, умноженной на увеличение скорости, деленной на количество элементов на запрос сохранения (для каждого элемента сверху), что дает: 21312,87 * 3,59 / 10 = 7651,32 составных записей / второй. Это число, которое MarkLogic должен стремиться достичь.

Итак, я изменил свои данные так, чтобы в каждом документе было по десять элементов, чтобы я мог сравнить количество документов в секунду с указанным выше числом. Снова без включенных индексов и с небольшим изменением — используйте 20 потоков вместо 50, чтобы не оставлять открытыми неиспользуемые соединения, и только 10 документов на пакет, а не 100 (поскольку документы теперь в десять раз больше, с десятью элементы каждого):

Общее время, затраченное на 100000 документов из десяти элементов: 31 секунда. Пропускная способность агрегатов по MarkLogic: 3225,80 / сек. Это примерно на 25% медленнее, чем для простых одноэлементных документов. Учитывая, что в 10 раз больше информации, это справедливый обмен!

Это означает, что MarkLogic, вероятно, отстает от Redis только в 2,37 раза. Даже при включенной индексации это, скорее всего, будет примерно в 3,5 раза медленнее. Учитывая все возможности, которые вы получаете от индексов в возможностях запросов в MarkLogic по сравнению с хранилищем значений ключей, вы должны спросить себя, зачем использовать хранилище значений ключей для хранения сложных агрегатов? Наверное, поэтому рынок баз данных NoSQL для документов все еще жив и работает!

Примечание: мне бы очень хотелось, чтобы кто-то с опытом тестирования Redis написал тест HMSET и HMGET для пакета, поэтому я могу получить некоторые реальные цифры, а не оценки в приведенном выше! Свяжитесь со мной, если вы знаете, как это сделать, пожалуйста!

Вывод

Что мы доказали? Наш главный вопрос был таков:

У меня есть и магазин документов, и магазин KV. Можно ли заменить оба на один, учитывая, что у меня есть данные и нагрузки запросов, которые могут обрабатываться обоими?

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

  1. Производительность хранилища ключей и значений значительно снижается благодаря строгому ведению журнала для обеспечения надежности данных
  2. Хранилище значений ключа может хранить только хэши, тогда как хранилище документов может хранить очень сложные иерархические структуры.
  3. Хранилище значений ключей не предоставляет возможности поиска или других расширенных запросов, в то время как MarkLogic

Вывод:

  • MarkLogic может действовать как очень быстрое хранилище агрегатов, и делает это, обеспечивая при этом очень быструю и сложную возможность запросов.
  • Если вам нужны невероятно быстрые скорости чтения, такие как кэш только для чтения, то использование Redis поверх хранилища документов может быть правильным подходом.
  • Не заменяйте хранилище документов хранилищем значений ключей, даже если оно поддерживает такие структуры, как хеши, поскольку снижение производительности, обеспечивающее долговечность, в сочетании с базовыми (и, следовательно, медленными в вашем приложении) возможностями запросов, снижает скорость Преимущество чистого хранилища ключей в памяти.

Есть несколько предостережений к этому исследованию:

  1. Большинство людей используют Redis как кэш в памяти, а не как хранилище первичных данных «золотой копии». Это правильный выбор, и он работает для многих
  2. Хранилища документов предоставляют больше возможностей по сравнению с простым хранилищем ключей. Вы можете обнаружить, что вам нужно настроить хранилище документов, а не устанавливать Redis перед ним, или заменить его Redis из-за функций, которые он не поддерживает.

Так что для большинства людей вышесказанное ничего не изменит. Если вы думаете: «Для приложений без безумной скорости чтения / записи — могу ли я просто использовать свое хранилище документов в одиночку?» — Я думаю, что мы доказали, что ответ «да», и этого нельзя сказать о замене хранилища документов хранилищем значений ключей.

Магазины Key-Value — отличная технология, но они нацелены на очень специфический рынок. Этот рынок нуждается в безумных скоростях чтения, а иногда и очень высоких скоростях записи. Они, как правило, не содержат основной копии данных, поэтому вы можете обменять долговечность и согласованность на прямую производительность. Это действительный выбор в этих случаях ограниченного использования.

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