blog-post

Manticore Search: 3 года после получения роли Sphinx

В мае 2017 года мы сделали форк Sphinxsearch 2.3.2, который мы назвали Manticore Search . Ниже вы найдете краткий отчет о Manticore Search как о форке Sphinx и наших достижениях с тех пор.

Почему мы сделали форк Sphinx?


Прежде всего, почему мы сделали форк? В конце 2016 года работа над Sphinxsearch была приостановлена. Пользователи, которые использовали Sphinx, и некоторые клиенты, поддерживавшие разработку проекта, были обеспокоены этим, потому что:

  • ошибки не исправлялись на протяжении длительных периодов времени
  • новые функции, которые долго обещались, не были реализованы
  • связь с командой Sphinx была нарушена

Спустя несколько месяцев ситуация не изменилась, и в середине июня 2017 года группа проактивных и опытных пользователей Sphinx и клиентов поддержки собралась и решила попробовать сохранить продукт в качестве форка под названием Manticore Search. Нам удалось собрать большую часть предыдущей команды Sphinx, которая уже работала в разных компаниях, привлечь инвестиции и в короткие сроки восстановить полноценную работу над проектом.

Каковы были наши цели?


Форк ставил перед собой три цели:

  1. Поддержка кода в целом: исправление ошибок, малые и крупные новые функции
  2. Поддержка пользователей Sphinx и Manticore
  3. Более интенсивная разработка продукта, чем это было раньше. К сожалению, к тому времени Elasticsearch уже обогнал Sphinx во многих отношениях.

Такие вещи, как:

  • отсутствие репликации
  • отсутствие авто ID
  • отсутствие JSON-интерфейса
  • отсутствие возможности создавать/удалять индекс на лету
  • отсутствие хранения документов
  • незрелые индексы в реальном времени
  • акцент на полнотекстовом поиске, а не поиске в целом

сделали Sphinx очень специализированным решением с необходимостью вручную настраивать его во многих случаях. К тому времени многие пользователи уже мигрировали на Elasticsearch. Это было обидно, потому что фундаментальные структуры данных и алгоритмы в Sphinx потенциально и фактически во многих случаях превосходили Elasticsearch по производительности. И SQL, который был гораздо лучше развит в Sphinx, чем в Elasticsearch даже сейчас, был привлекателен для многих.

В дополнение к поддержке существующих пользователей Sphinx, глобальная цель Manticore заключалась в реализации вышеупомянутых и других функций, которые сделали бы Manticore Search реальной альтернативой Elasticsearch в большинстве случаев использования.

Что мы уже сделали


Намного более активная разработка

Если вы посмотрите на статистику коммитов на github , вы можете увидеть, что как только произошел форк (середина 2017 года), темпы разработки значительно возросли:

img

За три с половиной года до марта 2021 года мы выпустили 39 новых версий. В 2020 году мы выпускали новую версию каждые deux месяца.

Репликация

Многие пользователи ждали репликации в Sphinx в течение многих лет. Одной из первых крупных функций, которую мы реализовали в Manticore, была репликация. Как и все в Manticore, мы постарались сделать это максимально простым в использовании. Например, чтобы подключиться к кластеру, вам нужно просто выполнить команду вроде этой:

JOIN CLUSTER posts at 'neighbour-server';

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

Репликация Manticore это:

  • синхронная
  • основана на библиотеке Galera, которая также используется в MariaDB и Percona XtraDB.

Авто ID

Без авто-id Sphinx / Manticore считались в основном просто расширением для другой базы данных (mysql, postgres и т.д.), поскольку должно было быть что-то, что генерирует ID. Мы реализовали авто-id на основе алгоритма UUID_SHORT. Уникальность гарантирована до 16 миллионов вставок в секунду на сервер, что должно быть достаточным в любых случаях.

mysql> create table idx(doc text);
Query OK, 0 rows affected (0.01 sec)

mysql> insert into idx(doc) values('abc def');
Query OK, 1 row affected (0.00 sec)

mysql> select * from idx;
+---------------------+---------+
| id                  | doc     |
+---------------------+---------+
| 1514145039905718278 | abc def |
+---------------------+---------+
1 row in set (0.00 sec)

mysql> insert into idx(doc) values('def ghi');
Query OK, 1 row affected (0.00 sec)

mysql> select * from idx;
+---------------------+---------+
| id                  | doc     |
+---------------------+---------+
| 1514145039905718278 | abc def |
| 1514145039905718279 | def ghi |
+---------------------+---------+
2 rows in set (0.00 sec)

Хранение документов

В Sphinx 2.3.2 и ранее вы могли сохранять оригинальные тексты документов только в строковых атрибутах, которые (как все атрибуты) должны были храниться в памяти для оптимальной производительности. Многие пользователи так делали, нерационально расходуя оперативную память, что было дорого и могло вызывать неожиданное падение производительности при больших объемах. В Manticore мы создали новый тип данных text, который сочетает полнотекстовую индексацию и хранение значения на диске с ленивым чтением (т.е. значение извлекается на самой последней стадии запроса). Значения полей “stored” не подлежат фильтрации и не могут быть отсортированы или сгруппированы. Они просто находятся в сжатом виде на диске, поэтому нет необходимости хранить их в MySQL/HBase/Postgres и других базах данных (если они действительно не нужны). Это оказалось очень полезной и часто используемой функцией. С тех пор Manticore теперь требует ничего, кроме себя, для реализации поискового приложения.

Индексы в реальном времени

В Sphinx 2.3.2 и ранее многие пользователи испытывали трудности с использованием индексов в реальном времени, поскольку это часто вызывало сбои и другие побочные эффекты. Мы исправили большинство известных ошибок и недостатков в дизайне, и мы все еще работаем над некоторыми оптимизациями (в основном связанными с автоматическим OPTIMIZE и изоляцией операций чтения/записи/объединения). Но уже можно с уверенностью сказать, что индексы в реальном времени могут использоваться в производственной среде, что, на самом деле, делают многие пользователи. Чтобы упомянуть несколько функций, которые мы добавили:

  • многопоточность: поиск в нескольких частях диска одного индекса в реальном времени выполняется параллельно
  • улучшения OPTIMIZE: по умолчанию части объединяются не в 1, а в количество ядер на сервере * 2 (это можно настроить через опцию cutoff ).

Мы работаем над автоматическим OPTIMIZE, чтобы пользователям не приходилось беспокоиться о компактации вообще.

charset_table = cjk, non_cjk

Ранее, если вы хотели поддерживать какой-либо язык, отличный от английского или русского, вам часто приходилось поддерживать большие массивы в charset_table. Это было неудобно. Мы упростили это, поместив все, что может понадобиться, во внутренние массивы charset_table, названные non_cjk (для большинства языков) и cjk (для китайского, корейского и японского). Массив non_cjk является умолчательным для charset_table. Теперь вы можете без проблем искать на английском, русском и, скажем, турецком языках:

mysql> create table idx(doc text);
Query OK, 0 rows affected (0.01 sec)

mysql> insert into idx(doc) values('abc абв öğrenim');
Query OK, 1 row affected (0.00 sec)

mysql> select * from idx where match('abc');
+---------------------+----------------------+
| id                  | doc                  |
+---------------------+----------------------+
| 1514145039905718280 | abc абв öğrenim      |
+---------------------+----------------------+
1 row in set (0.00 sec)

mysql> select * from idx where match('абв');
+---------------------+----------------------+
| id                  | doc                  |
+---------------------+----------------------+
| 1514145039905718280 | abc абв öğrenim      |
+---------------------+----------------------+
1 row in set (0.00 sec)

mysql> select * from idx where match('ogrenim');
+---------------------+----------------------+
| id                  | doc                  |
+---------------------+----------------------+
| 1514145039905718280 | abc абв öğrenim      |
+---------------------+----------------------+
1 row in set (0.00 sec)

Официальный образ Docker

Мы выпустили и поддерживаем официальный образ docker для Manticore Search. Теперь вы можете запустить Manticore за считанные секунды в любом месте, где есть docker.

  ~ docker run --name manticore --rm -d manticoresearch/manticore && docker exec -it manticore mysql && docker stop manticore

525aa92aa0bcef3e6f745ddeb11fc95040858d19cde4c9118b47f0f414324a79
mysql> create table idx(f text);
mysql> desc idx;
+-------+--------+----------------+
| Field | Type   | Properties     |
+-------+--------+----------------+
| id    | bigint |                |
| f     | text   | indexed stored |
+-------+--------+----------------+

Кроме того, тег manticore:dev всегда указывает на самую последнюю версию разработки Manticore Search.

Репозиторий пакетов

Все новые релизы и свежие версии разработки можно найти на https://repo.manticoresearch.com/

Оттуда вы также можете легко установить Manticore через YUM и APT . Мы также поддерживаем Homebrew и поддерживаем сборки для Windows.

NLP: Обработка Естественного Языка

На стороне NLP мы внесли следующие улучшения:

  • Сегментация китайского языка с использованием библиотеки ICU
  • стоп-слова по умолчанию для большинства языков из коробки:
mysql> create table idx(doc text) stopwords='en';
Query OK, 0 rows affected (0.05 sec)

mysql> call keywords('to be or not to be that is the question', 'idx');
+------+-----------+------------+
| qpos | tokenized | normalized |
+------+-----------+------------+
| 10   | question  | question   |
+------+-----------+------------+
1 row in set (0.01 sec)
mysql> insert into idx(doc) values('Polly wants a cracker');
Query OK, 1 row affected (0.09 sec)

mysql> select highlight() from idx where match('polly cracker');
+-------------------------------------+
| highlight()                         |
+-------------------------------------+
| <b>Polly</b> wants a <b>cracker</b> |
+-------------------------------------+
1 row in set (0.10 sec)

Новый режим многозадачности

Для многозадачности Manticore теперь использует корутины. В дополнение к тому, что код стал гораздо проще и надежнее, больше не требуется использовать разные значения dist_threads для разных индексов, чтобы обеспечить оптимальную параллелизацию поиска по ним. Теперь существует глобальная настройка threads, которая по умолчанию равна количеству ядер на сервере. В большинстве случаев вам не нужно трогать её для достижения оптимальной производительности.

Поддержка OR в WHERE

В Sphinx 2/3 вы не можете легко фильтровать по атрибутам, используя оператор OR, что является большим ограничением. Мы исправили это в Manticore:

mysql> select i, s from t where i = 1 or s = 'abc';
+------+------+
| i    | s    |
+------+------+
|    1 | abc  |
|    1 | def  |
|    2 | abc  |
+------+------+
3 rows in set (0.00 sec)

Sphinx 3:
mysql> select * from t where i = 1 or s = 'abc';
ERROR 1064 (42000): sphinxql: syntax error, unexpected OR, expecting $end near 'or s = 'abc''

Поддержка JSON-протокола через HTTP

SQL — это здорово. Мы любим SQL. И в Sphinx / Manticore всё, что касается синтаксиса запросов, можно сделать через SQL. Но есть ситуации, когда лучшее решение — использовать интерфейс JSON, например, как в Elasticsearch. SQL прекрасно подходит для проектирования запросов, тогда как JSON отлично работает, когда вам нужно интегрировать сложный запрос в ваше приложение.

Кроме того, HTTP позволяет делать много интересных вещей: использовать внешние HTTP балансировщики нагрузки и прокси, что позволяет легко реализовать аутентификацию, RBAC и т.д.

Новые клиенты для большего количества языков

Even easier than using the JSON over HTTP is to to use a client for a specific programming language your application is written in. We’ve implemented new clients for php , python , java , javascript , elixir , go . Most of them are based on the new JSON interface and their code is generated automatically, allowing us to add new features to the clients much faster.

HTTPS support

Security matters. We’ve made HTTPS support available out of the box. It’s still better not to expose Manticore Search instance to the internet as there is no built-in authentication, but it’s now safer to transfer queries and results from a client to Manticore Search over the LAN. SSL for mysql-interface is also supported.

FEDERATED support

In addition to SphinxSE (a built-in mysql engine that allows you to integrate Sphinx/Manticore more closely with mysql) you can now use MySQL’s FEDERATED engine which is available in MySQL and MariaDB.

ProxySQL support

ProxySQL is also supported and you can use it to make quite interesting things that expand capabilities of Manticore Search.

RT mode

One of the main changes we’ve made was the imperative (i.e. via CREATE/ALTER/DROP table) way of working with Manticore. As you can see from the SQL examples above you don’t need to define an index in config any more. As in other databases, you can now create, alter and delete indexes in Manticore on the fly without the need to edit config, restart the instance, delete real-time index files and all that hassle. Data schema is now completely separated from server’s settings. And that is the default mode. We call it RT mode.

But the declarative mode (we call it Plain mode) is still supported as well. We do not consider it a rudiment and do not plan to get rid of that. Just as you can communicate with Kubernetes the both ways either via yaml files or via specific commands, you can communicate with Manticore similarly too:

  • you can describe everything in a config and benefit the possibility of easy config porting and faster indexes deployment,
  • or you can create indexes on the fly which allows to integrate it easier to your application

It is not possible and not in plans to mix the use of modes.

Percolate index

The normal way of doing searches is to store documents we want to search and perform queries against them. However there are cases when we want to apply a query to an incoming new document to signal the matching. There are some scenarios where this is wanted. For example a monitoring system doesn’t just collect data, but it’s also desired to notify user on different events. That can be reaching some threshold for a metric or a certain value that appears in the monitored data. Another similar case is news aggregation. You can notify the user about any fresh news, but user might want to be notified only about certain categories or topics. Going further, they might be only interested about certain “keywords”. All this is now possible in Manticore if you use a percolate index.

mysql> create table t(f text, j json) type='percolate';
mysql> insert into t(query,filters) values('abc', 'j.a=1');
mysql> call pq('t', '[{"f": "abc def", "j": {"a": 1}}, {"f": "abc ghi"}, {"j": {"a": 1}}]', 1 as query);
+---------------------+-------+------+---------+
| id                  | query | tags | filters |
+---------------------+-------+------+---------+
| 8215503050178035714 | abc   |      | j.a=1   |
+---------------------+-------+------+---------+

Works faster than in Elasticsearch .

New user-friendly documentation - https://manual.manticoresearch.com

For key Manticore Search functionality there are examples for most supported clients. Search in the manual of course uses Manticore Search as a backend. What else:

  • Smart search results highlighting in search results
  • HTTP examples can be copied in one click directly as a curl command with parameters
  • In addition, we have specially registered short domain mnt.cr, so that you can very quickly find info on smth you need right now by CTRL-T/CMD-T in your browswer and typing for example mnt.cr/proximity , mnt.cr/quorum , mnt.cr/percolate .

Interactive Courses - https://play.manticoresearch.com

To make it easier to get started with Manticore Search we’ve made the platform for interactive courses https://play.manticoresearch.com and of course the courses themselves, that you can take right from your browser without installing anything at all. In few seconds you can see how Manticore Search replication works or how to highlight search results

Github as a bug tracker

We use Github as a public bug/task tracker.

Sphinx 3


Sphinx 3.0.1 был выпущен в декабре 2017 года. До октября 2018 года было выпущено еще три обновления и еще одно в июле 2020 года (3.3.1, последняя версия на март 2021 года). Появилось много интересных функций, включая вторичные индексы и некоторые возможности машинного обучения. И в чем же проблема? Почему людям вообще нужен Manticore? Одна из причин в том, что, к сожалению, ни первый релиз Sphinx 3, ни последний в настоящее время не являются открытым исходным кодом:

  • обеим в том смысле, что код Sphinx 3 недоступен
  • и в широком смысле открытого программного обеспечения . На странице загрузок говорится , что Sphinx теперь доступен по лицензии “отложенное FOSS”. Что именно представляет собой эта лицензия и где её можно найти, не раскрывается. Неясно:
  • является ли она все еще GPLv2 (т.е. “отложенное FOSS” означает отложенный GPLv2), поскольку код, вероятно, основан на Sphinx 2, который является GPLv2 (как Manticore). Но тогда где исходный код?
  • или это не GPLv2, потому что никакая лицензия не приложена к бинарникам, и неизвестно, основан ли код вообще на Sphinx 2 или нет? Применяются ли ограничения GPLv2? Можно ли распространять бинарные файлы Sphinx 3 по своему усмотрению, поскольку текст лицензии отсутствует?
  • С июля 2020 года не было выпущено ни одной версии. Есть много ошибок , включая серьезные сбои. Когда они будут исправлены?

Существует много вопросов и нет ответов. Всё это делает использование Sphinx 3 очень рискованным для компаний и индивидуумов, заботящихся о правовой стороне дела и стабильности проекта. Не многие компании имеют возможность инвестировать время своих сотрудников в проект, который выглядит замороженным и имеет столь неясную лицензию.

В общем, Sphinx 3 теперь можно рассматривать как проприетарное решение для ограниченного круга пользователей с очень специфическими целями. Жаль, что мир открытого программного обеспечения потерял Sphinx. Мы можем только надеяться, что что-то изменится в будущем.

Какие есть бенчмарки?


Да! Давайте протестируем набор данных , состоящий из более чем 1M комментариев с HackerNews и числовых атрибутов.

Больше о тесте:

  • простой индекс построен на основе набора данных. Размер файлов индекса составляет около 1 гигабайта
  • набор различных запросов (132 запроса) от полнотекстового поиска до фильтрации и группировки
  • докеры работают на голом сервере с разными ограничениями по памяти
  • мы используем SQL через клиент mysqli из PHP-скрипта для отправки запросов
  • перед каждым новым запросом мы очищаем все кеши, включая кеш ОС и перезапускаем docker, затем проводим 5 попыток, наименьшее время отклика идет в статистику.

Результаты:

Ограничение 100 мегабайт:

img

Ограничение 500 мегабайт:

img

Ограничение 1000 мегабайт:

img

Будущее Manticore Search


Итак, у нас уже есть активно развиваемый продукт с ясной лицензией открытого программного обеспечения GPLv2 с репликацией, авто-идентификацией, корректно работающими индексами в реальном времени, JSON интерфейсом, хорошей документацией, интерактивными курсами и многим другим. Что дальше? Наш дорожная карта такова:

Новый движок Manticore

С начала 2020 года мы работаем над библиотекой столбцового хранения и обработки с индексацией по умолчанию (в отличие, скажем, от Clickhouse). Для пользователей Manticore и Sphinx это решит следующие проблемы:

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

У нас уже есть бета-версия готова и вот некоторые первые результаты сравнения Manticore Columnar Library + Manticore Search с Elasticsearch на том же наборе данных, что и выше (исключая полнотекстовые запросы, т.е. в основном запросы на группировку):

img

Еще предстоит проделать много работы. Библиотека доступна под более либеральной лицензией открытого программного обеспечения Apache 2.0 и может использоваться в Manticore Search, а также в других проектах (в Sphinx тоже, если им это интересно).

Авто OPTIMIZE

Мы понимаем, как неудобно вручную вызывать OPTIMIZE для компактирования индексов в реальном времени. Мы работаем над решением этой проблемы и надеемся, что это будет включено в следующий релиз. Следите за нами в twitter , чтобы не пропустить это.

Интеграция с Kibana

Поскольку пользователи теперь могут проводить больше аналитики с новым движком Manticore, было бы неплохо также визуализировать это легко. Grafana классная, но может быть немного сложной для использования для полнотекстового поиска. Kibana также неплоха, много людей знают и используют её. У нас есть альфа-версия интеграции между Manticore Search и Kibana. Она не доступна публично, но как только мы закончим исправление ошибок и сможем рассмотреть её как бета, она будет открыта.

Интеграция с Logstash

Manticore Search уже имеет JSON протокол. Мы собираемся улучшить методы PUT и POST, чтобы сделать их совместимыми с Elasticsearch для запросов INSERT/REPLACE. Кроме того, мы планируем сделать возможным создание индекса на лету на основе первых вставленных документов. Всё это позволит вам записывать данные в Manticore Search вместо Elasticsearch из Logstash, Fluentd, Beats и подобных инструментов.

Автоматическое шардирование

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

Альтернатива Logstash

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

Если вам нравится то, что мы делаем, следите за нами:

Установить Manticore Search

Установить Manticore Search