Чтение и запись документов
Введение
Каждый индекс в Elasticsearch разделен на фрагменты, и каждый фрагмент может иметь несколько копий. Эти копии известны как группа реплик и должны синхронизироваться при добавлении или удалении документов. Если этого не сделать, чтение из одной копии может привести к значительно отличающимся результатам по сравнению с чтением из другой. Процесс синхронизации копий фрагмента и предоставления чтений из них называется моделью репликации данных.
Модель репликации данных Elasticsearch основана на модели «первичная-резервная» и подробно описана в статье PacificA исследовательского отдела Microsoft. Эта модель основана на наличии одной копии из группы реплик, которая выполняет роль первичного фрагмента. Другие копии называются фрагментами-репликами. Первичный фрагмент служит основным входом для всех операций индексирования. Он отвечает за их валидацию и проверку правильности. После того, как операция индексирования принята первичным фрагментом, первичный фрагмент также отвечает за репликацию операции в другие копии.
Цель этого раздела — дать общее представление о модели репликации Elasticsearch и обсудить ее последствия для различных взаимодействий между операциями записи и чтения.
Базовая модель записи
Каждая операция индексирования в Elasticsearch сначала решается для группы реплик с помощью маршрутизации, как правило, на основе идентификатора документа. После определения группы реплик операция передается внутри текущему первичному фрагменту группы. Этот этап индексирования называется этапом координации.
Следующий этап индексирования — этап первичного фрагмента, выполняемый на первичном фрагменте. Первичный фрагмент отвечает за валидацию операции и ее передачу другим репликам. Поскольку реплики могут быть оффлайн, первичному фрагменту не требуется репликация во все реплики. Вместо этого Elasticsearch поддерживает список копий фрагментов, которые должны получить операцию. Этот список называется синхронизированными копиями и поддерживается узлом-мастером. Как следует из названия, это набор «хороших» копий фрагментов, которые гарантированно обработают все операции индексирования и удаления, которые были подтверждены пользователю. Первичный фрагмент отвечает за поддержание этого инварианта и, следовательно, должен реплицировать все операции в каждую копию в этом наборе.
Первичный фрагмент следует этому основному потоку:
- Проверить входящую операцию и отклонить ее, если она структурно некорректна (Пример: есть поле объекта, где ожидается число)
- Выполнить операцию локально, т. е. индексировать или удалить соответствующий документ. Это также проверит содержимое полей и отклонит, если потребуется (Пример: значение ключевого слова слишком длинно для индексирования в Lucene).
- Передать операцию каждой реплике в текущем наборе синхронизированных копий. Если реплик несколько, это делается параллельно.
- После того, как все синхронизированные реплики успешно выполнили операцию и ответили первичному фрагменту, первичный фрагмент подтверждает успешное завершение запроса клиенту.
Каждая синхронизированная копия реплики выполняет операцию индексирования локально, чтобы иметь копию. Этот этап индексирования — этап реплики.
Эти этапы индексирования (координации, первичного и реплики) выполняются последовательно. Для включения внутренних повторов срок действия каждого этапа охватывает срок действия каждого последующего этапа. Например, этап координации не завершается до тех пор, пока каждый этап первичного фрагмента, который может быть распределен по разным первичным фрагментам, не завершится. Каждый этап первичного фрагмента не завершится, пока синхронизированные реплики не закончат индексирование документов локально и не ответят на запросы репликации.
Обработка ошибок
При индексировании могут возникнуть различные проблемы — жесткие диски могут повредиться, узлы могут отключиться друг от друга, или ошибка конфигурации может привести к сбою операции на реплике, несмотря на успешное выполнение на первичном фрагменте. Такие случаи редки, но первичный фрагмент должен реагировать на них.
В случае сбоя первичного фрагмента узел, на котором размещен первичный фрагмент, отправит сообщение мастер-узлу об этом. Операция индексирования будет ожидать (до 1 минуты, по умолчанию) до того, как мастер-узел повысит одну из реплик до нового первичного фрагмента. Затем операция будет передана новому первичному фрагменту для обработки. Обратите внимание, что мастер-узел также отслеживает состояние узлов и может принять решение о предварительном понижении первичного фрагмента. Это обычно происходит, когда узел, на котором находится первичный фрагмент, изолирован от кластера из-за сетевой проблемы. Дополнительные сведения см. в разделе здесь.
После успешного выполнения операции на первичном фрагменте первичному фрагменту необходимо обработать потенциальные ошибки при ее выполнении на фрагментах-репликах. Это может быть вызвано фактической ошибкой на реплике или проблемой с сетью, которая препятствует выполнению операции на реплике (или предотвращает отклик реплики). Все эти ситуации приводят к тому, что реплика, входящая в набор синхронизированных реплик, пропускает операцию, которая должна быть подтверждена. Чтобы избежать нарушения инварианта, первичный фрагмент отправляет сообщение мастер-узлу с запросом об удалении проблемного фрагмента из набора синхронизированных реплик. Только после подтверждения удаления фрагмента мастер-узлом первичный фрагмент подтверждает операцию. Обратите внимание, что мастер-узел также даст указание другому узлу начать построение новой копии фрагмента для восстановления работоспособности системы.
При передаче операции репликам первичный фрагмент будет использовать реплики для проверки, является ли он активным первичным фрагментом. Если первичный фрагмент был изолирован из-за сетевого разрыва (или длительной операции GC), он может продолжать обрабатывать входящие операции индексирования, прежде чем осознает, что его понизили. Операции, которые поступают от устаревшего первичного фрагмента, будут отклонены репликами. Когда первичный фрагмент получает ответ от реплики с отказом в выполнении запроса, потому что он больше не является первичным, он обращается к мастер-узлу и узнает, что его заменили. Затем операция перенаправляется на новый первичный фрагмент.
Базовая модель чтения
Чтение в Elasticsearch может быть очень простым по идентификатору или сложным запросом поиска с комплексными агрегациями, требующими значительных вычислительных ресурсов. Прелесть модели «первичный-резервный» заключается в том, что она поддерживает идентичность всех копий фрагментов (за исключением операций в процессе). Поэтому одной синхронизированной копии достаточно для обработки запросов на чтение.
Когда узел получает запрос на чтение, он отвечает за пересылку его узлам, на которых находятся соответствующие фрагменты, объединение ответов и отправку ответа клиенту. Мы называем этот узел координирующим узлом для этого запроса. Основной поток действий следующий:
- Решить запросы на чтение для соответствующих фрагментов. Обратите внимание, что поскольку большинство запросов поиска будут отправляться на один или несколько индексов, они, как правило, нуждаются в чтении из нескольких фрагментов, каждый из которых представляет собой отдельный подмножество данных.
- Выбрать активную копию каждого соответствующего фрагмента из группы реплик фрагмента. Это может быть первичный фрагмент или реплика. По умолчанию Elasticsearch использует адаптивную селекцию реплики для выбора копий фрагментов.
- Отправить запросы на чтение уровня фрагмента выбранным копиям.
- Объединить результаты и отправить ответ. Обратите внимание, что в случае поиска по идентификатору только один фрагмент важен, и этот шаг можно пропустить.
Ошибки фрагментов
Если фрагмент не отвечает на запрос на чтение, координирующий узел отправляет запрос другой копии фрагмента в той же группе реплик. Повторяющиеся ошибки могут привести к отсутствию доступных копий фрагмента.
Для обеспечения быстрых ответов следующие API будут отвечать частичными результатами, если один или несколько фрагментов выйдут из строя:
Ответы с частичными результатами по-прежнему имеют код состояния HTTP 200 OK. Ошибки фрагментов обозначаются полями timed_out и _shards в заголовке ответа.
Некоторые простые последствия
Каждый из этих базовых потоков определяет поведение Elasticsearch как системы для чтения и записи. Кроме того, поскольку запросы на чтение и запись могут выполняться одновременно, эти два основных потока взаимодействуют друг с другом. Это влечет за собой несколько последствий:
- Эффективное чтение
- При нормальной работе каждая операция чтения выполняется один раз для каждой соответствующей группы реплик. Только при сбоях выполняется несколько копий одного и того же фрагмента, выполняющих один и тот же поиск.
- Чтение без подтверждения
- Поскольку первичный фрагмент сначала индексирует локально, а затем реплицирует запрос, возможно, что одновременное чтение уже увидит изменение, прежде чем оно будет подтверждено.
- По умолчанию две копии
- Эта модель может быть отказоустойчивой, при этом поддерживаются только две копии данных. Это отличается от систем на основе кворумов, где минимальное количество копий для отказоустойчивости равно 3.
Сбои
При сбоях возможно следующее:
- Один фрагмент может замедлить индексирование
- Поскольку первичный узел ожидает всех реплик в наборе синхронизированных копий во время каждой операции, один медленный фрагмент может замедлить всю группу репликации. Это цена, которую мы платим за эффективность чтения, упомянутую выше. Конечно, один медленный фрагмент также замедлит неудачные запросы, которые были перенаправлены на него.
- Негарантированные чтения
- Изолированный первичный узел может экспонировать записи, которые не будут подтверждены. Это происходит из-за того, что изолированный первичный узел поймёт, что он изолирован, только когда он отправит запросы своим репликам или обратится к мастеру. В этот момент операция уже проиндексирована в первичном узле и может быть прочитана в ходе одновременного чтения. Elasticsearch минимизирует этот риск, посылаю запросы мастеру каждые секунду (по умолчанию) и отклоняя операции индексирования, если мастер не найден.
Конец айсберга
Данный документ предоставляет общий обзор того, как Elasticsearch обрабатывает данные. Конечно, происходит гораздо больше под капотом. Такие вещи, как первичные термины, публикация состояния кластера и выбор мастера, играют роль в корректной работе этой системы. В этом документе также не рассматриваются известные и важные ошибки (как закрытые, так и открытые). Мы признаём, что GitHub трудно отслеживать. Чтобы помочь людям следить за ними, мы поддерживаем посвящённую страницу отказоустойчивости на нашем веб-сайте. Мы настоятельно рекомендуем её прочитать.
© 2023-2025 Elasticsearch
As of September 2024, Elasticsearch is available under a choice of three licenses: the Server Side Public License (SSPL), the Elastic License, or the AGPLv3 (OSI approved).
Elasticsearch and the Elasticsearch logo are trademarks of Elasticsearch B.V., registered in the U.S. and in other countries.
https://www.elastic.co/guide/en/elasticsearch/reference/7.17/docs-replication.html