В рамках этой статьи я поделюсь опытом использования Elastic Search во внутренних продуктах 2ГИС, в частности, в собственной системе для организации Call-центра. А также расскажу, какие проблемы мы смогли решить, используя этот поисковый движок.
В недрах 2ГИС есть проект InfoRussia, с помощью которого операторы звонят и сверяют карточки организаций. В базе хранится 13 млн. карточек с данными об организациях России, общий размер которых более 150 ГБ. Данные хранятся в реляционной базе, частично разложенные в таблицы, частично — в xml-полях.
Список проблем и задач, которые требовалось решить:
1. Искать по большому количеству критериев.
2. Добавлять информацию в индекс без полной переиндексации.
3. Выгружать данные без блокировки таблиц.
4. Снизить нагрузки на базу, убрать большие join по таблицам.
5. Поддерживать мультиязычный поиск без серьезных инвестиций в разработку.
Проанализировав доступные решения, мы выбрали Elastic, так как он удовлетворял большинству требований.
Исходя из аналитики, требования были следующие.
Функциональные требования:
- Поиск по критериям (точное совпадение по одному значению или по списку значений).
- Поиск по диапазону (числа, даты).
- Полнотекстовый поиск (морфология, шаблоны (wildcard)).
- Булевый поиск (объединение критериев поиска по И/ИЛИ).
Нефункциональные требования:
- Надежность (поддержка распределенных индексов).
- Масштабируемость (возможность распределения на несколько серверов и поддержка всей необходимой инфраструктуры «из коробки»).
- Индексация в режиме «реального» времени (новые данные должны быть проиндексированы без явной необходимости полного перестроения индекса и в «разумное» время).
- Конфигурируемость (в частности, добавление новых полей в индекс без необходимости его полного перестроения — требуется для индексации дополнительных атрибутов).
- Удобство использования (наличие «клиентов» под нужные платформы/языки, использование общедоступных протоколов, например, HTTP).
- Производительность (какое время отклика должно быть обеспечено при нагрузке 300 операторов онлайн, объем данных — вся Россия).
- Стоимость владения/поддержки.
Основные кандидаты на роль поискового движка — ElasticSearch, Solr и Sphinx.
Solr не подошел потому, что при онлайн-индексации, скорость поиска сильно падает (подробнее можно узнать из статьи). Картинка ниже иллюстрирует данный факт. Кроме того, можно ознакомиться со статьей, которая разбирает Solr vs ElasticSearch в деталях.
Следующий кандидат, которого мы рассматривали — Sphinx. ElasticSearch выиграл за счет поддержки шардинга, репликации, возможности составлять сложные запросы и вытягивать из поиска оригинальные данные.
Поиск
Первый же прототип, который был сделан для поиска на базе ES, оказался настолько хорош, что сразу же переехал в боевое приложение и живет там до сих пор.
Когда проект только начинался, в ES еще не было механизма River, поэтому мы написали свой job для переиндексации базы.
Сервис берет данные об измененных сущностях и складывает их в индекс ES, пока не обработает всю очередь. Для быстрой загрузки можно применить следующие оптимизации:
1. Использовать bulk операции.
2. Установить параметр refresh_interval в -1.
Этот параметр отвечает за время внутренней переиндексации в ES. После того, как все данные загружены в поиск, необходимо вернуть значение по умолчанию. При использовании данного метода, всё, что мы загружаем, не будет анализироваться и, соответственно, не будет доступно для поиска, пока не произойдет внутренняя переиндексация.
Поиск в нашем проекте индексируется онлайн, за раз мы индексируем 100 карточек.
После того как данные оказались в индексе, мы можем по ним искать.
Задачи, которые требуют быстрого поиска по различным параметрам мы решаем с использованием Elastic Search.
Например, имея 13 млн. карточек в базе, нужно просмотреть все телефоны карточки и найти такой же телефон (в нашей схеме данных телефоны хранятся внутри xml поля). Такой запрос к MS SQL базе занимает до 10-15 минут. Elastic Search справляется с этой задачей за несколько миллисекунд.
Итак, основные кейсы, которые мы решили с помощью Elastic Search:
Поиск карточек, у которых есть такой же адрес (в окне редактирования карточки)
При заведении новой карточки в здании, оператор видит, какие еще есть организации в этом здании, и может сверить информацию по организациям, которые находятся рядом.
Поиск карточек, у которых есть такой же телефон
Бывает и так, что по одному телефону можно сверить несколько организаций, поэтому мы показываем, какие еще карточки имеют такой же контакт.
Поиск карточек в форме поиска
Помимо всего прочего, в приложении есть форма поиска, которая позволяет искать по огромному количеству критериев. Данная форма используется для планирования выверки организаций, контроля качества и т.д.
В каждой вкладке еще по 4–5 параметров для запроса к поисковому движку.
Строить индексы в реляционной базе по такому количеству полей — довольно расточительно, поэтому Elastic помог нам в решении этой проблемы.
Выгрузка данных
Одним из бизнес-кейсов приложения, является поддержка выгрузки данных в Excel. Выгрузки используются различными специалистами для анализа качества собранных данных, планирования работы специалистов по сбору информации.
Для выгрузки данных из поиска в Excel мы так же используем ES. Это очень удобно, так как Elastic поддерживает специальный режим для выборки данных — Scroll.
Режим Scroll позволяет «зафиксировать» результаты запроса к поиску и получать эти результаты небольшими порциями.
У данного режима есть ряд ограничений. Например, нельзя сортировать данные (на самом деле, можно, но с падением производительности и расходом памяти).
Наши испытания показали, что всю базу 2ГИС мы можем выгрузить в Excel-файл за сутки.
При организации выгрузок такого большого объема, большое значение имеет наличие всех необходимых данных в хранилище. Таким образом мы используем Elastic как NoSQL хранилище, в котором данные, необходимые только для выгрузки, хранятся в неиндексируемых полях.
На скриншоте видно, что в индексе лежат денормализованные данные, мы храним id города и его название вместе с карточкой.
Кроме того, можно сделать вложенные сущности, например, время работы и рубрики в которых размещается организация.
Поддержка европейских языков
Должен отметить этот пункт отдельно. Не так давно, 2ГИС запустил несколько международных проектов. Для поддержки Праги, Лимасола, Падуи нам не потребовалось дорабатывать поисковые запросы. Мы просто загрузили карточки в индекс и поиск сам заработал.
Недавно мы немного доработали запросы, для поддержки поиска с учетом диакритик, но, фактически, это встроенная функция Elastic.
Обеспечение надежности и отказоустойчивости
Elastic поддерживает как шардинг, так и установку нескольких нод в кластер. Сейчас у нас собран кластер из двух нод, которые обслуживают 300 человек онлайн.
За 2 года эксплуатации проблемы с поисковой машиной случались только из-за падения виртуальных машин или иных проблем с инфраструктурой. Как и любой поисковый движок, Elastic любит хорошие диски и оперативную память, поэтому рекомендуется при проведении нагрузочного тестирования обратить особое внимание на эти параметры.
Заключение
Elastic Search полностью соответствует нашим требованиям к поисковому движку и позволил в кратчайшие сроки реализовать важную бизнес-фичу. Надежность, скорость и простота использования — вот те слагаемые, комбинация которых позволила нам сделать выбор в его сторону. Безусловно, есть и другие решения на рынке, обзор которых находится за рамками этой статьи. Целью статьи было показать какие задачи в бизнес-приложениях можно закрыть с помощью бесплатного Elastic Search.
Учитывая наш позитивный опыт применения Elastic, другие внутренние команды начали использовать этот поисковый движок у себя в проектах.
Автор: DeManiaC