Поиск лучшей формулы переиндексации Elasticsearch

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

Проблема в том, что эти изменения в Elasticsearch - непростые задачи, они не так просты, как выполнение команд, таких как операторы ALTER, в обычных реляционных базах данных. Фактически, большинство данных и настроек в Elasticsearch неизменяемы, что означает, что изменения должны выполняться путем удаления и создания. Например, Elasticsearch обрабатывает запросы на обновление данных, удаляя существующую запись и вставляя обновленную. Следовательно, миграция данных неизбежна при изменении настроек хранилища данных, а это означает, что вам необходимо создать новое хранилище данных с обновленной конфигурацией и перенести все существующие данные в новую. Звучит довольно сложно, не правда ли?

Сложно выполнить миграцию данных, сохраняя при этом НУЛЕВОЕ время простоя для круглосуточных систем с постоянными входящими запросами. Без продуманного планирования миграции ваши системы могут оказаться в опасности или пострадать от неожиданных сбоев.

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

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

Краткий обзор Elasticsearch

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

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

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

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

Действие по копированию данных из одного индекса в другой называется переиндексированием. Elasticsearch предлагает различные варианты переиндексации, такие как перенос данных целиком или частичная миграция с помощью запроса.

Индексы в Elasticsearch могут иметь вторичное имя (например, псевдоним). Это полезная функция, особенно для поддержки индексов с разными версиями. Например, приложение указывает на псевдоним индекса «Продукты», который назначается конкретной версии - Product_v1. Чтобы переключиться на индексирование Products_v2, это можно сделать, просто обновив псевдоним, и это изменение будет прозрачным для приложения. Следовательно, мы переключаемся на новый индекс после завершения переиндексации, присваивая псевдоним новому индексу.

Самый простой подход, если время простоя приемлемо

После быстрого знакомства с Elasticsearch пришло время погрузиться в подходы к переиндексации.

Самый простой способ перенести данные в новый индекс - заморозить данные, предварительно отключив систему. Затем скопируйте все существующие данные в новый индекс, а затем возобновите работу системы с подключением к новому индексу.

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

Перенос данных, сохраняя систему в сети

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

Хотя простоев нет, это не идеальный подход. Поскольку самые последние обновления данных еще не скопированы в новый индекс, может возникнуть ошибка «Запись не найдена», поскольку ваша система переключается на новый индекс на шаге 2. Ситуация может немного улучшиться, если мы изменим последовательность шага 2. и шаг 3. Однако команда переиндексации Elasticsearch может сделать только статический моментальный снимок данных. Та же ошибка может возникнуть, если ваша система обрабатывает постоянный объем входящих запросов.

Переиндексирование без потери данных

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

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

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

Причина в том, что переиндексация требует интенсивного использования ЦП и операций ввода-вывода. Вместе с обновлением данных в реальном времени для нового индекса кластер Elasticsearch может быть перегружен большой нагрузкой и, в конечном итоге, выйдет из строя в худшем случае.

Как выполнить переиндексацию, но не перегружать кластер Elasticsearch?

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

Чтобы уменьшить потребление ресурсов, мы можем сначала создать новый индекс без осколка реплики, а затем создать осколки реплик после завершения переиндексации. По моему опыту, использование ресурсов переиндексации можно сократить примерно на 30%.

На диаграмме ниже показана улучшенная версия предыдущего подхода. Новый индекс создается только с первичными осколками с включенной синхронизацией данных в приложении в начале. Затем дайте команду кластеру Elasticsearch создать шарды реплик после завершения переиндексации. Наконец, переключите псевдоним на новый индекс.

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

Этот подход хорош, но он вводит дополнительный шаг для создания реплик. Однако невозможно отменить процесс, если что-то пойдет не так. Напротив, Elasticsearch позволяет нам в любой момент остановить процесс переиндексации.

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

Мы минимизируем риск, переместив действия по обновлению данных, чтобы снизить рабочую нагрузку на кластер Elasticsearch.

Оптимизировать использование ресурсов кластера

Идея состоит в том, чтобы избежать наложения дополнительной рабочей нагрузки на кластер во время выполнения переиндексации и создания реплики на шаге 1 и шаге 2 соответственно, как показано на схеме ниже. Это можно сделать, переместив шаг обновления данных в реальном времени для нового индекса с шага 1 на шаг 3, который происходит после завершения создания реплики. Такой подход снижает нагрузку на кластер, снижая вероятность взрыва кластера из-за большой рабочей нагрузки.

Наконец, точно настройте параметр регулирования операций переиндексации в зависимости от емкости вашего кластера Elasticsearch. Скорость переиндексации ограничена определенным количеством документов в секунду таким образом, чтобы контролировать использование ресурсов.

Шаг 3, по-видимому, включает в себя более тяжелую загрузку как обновлений данных, вводимых из входящего трафика в реальном времени, так и переиндексации в новом индексе с шардами реплик. Следовательно, переиндексация должна быть ограничена более низкой скоростью, скажем, 1000 документов в секунду, в то время как повторная индексация на шаге 1 может позволить более высокую скорость, скажем, 1500 документов в секунду.

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

Спасибо за чтение

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