Структура Подсистемы

Основные элементы

В Подсистеме определяются следующие основные структурные единицы:

  • Документ — это единица хранения информации (текста или структурированных данных) в формате JSON, которая может интерпретироваться следующим образом:
    • в базе данных некоторых единиц информации документ может представлять один экземпляр единицы информации;
    • при выполнении поиска информации Подсистема возвращает документы, связанные с этим поиском;
    • документ представляет собой строку в традиционной базе данных.
  • Индекс – это набор документов, который может интерпретироваться следующим образом:
    • в базе данных единиц информации индекс представляет собой все экземпляры единиц информации;
    • при выполнении поиска информации запрашиваются данные, содержащиеся в индексе;
    • индекс представляет собой таблицу базы данных в традиционной базе данных.
  • Узлы – один или несколько серверов, на которых функционирует Подсистема и которые хранят данных и обрабатывают поисковые запросы.
  • Шаблон компонента — многократно используемый объект с настройками, сопоставлениями и псевдонимами, который можно привязать к шаблону индекса.
  • Шаблон индекса — заранее заданная структура, используемая для организации и хранения данных в базе данных или поисковом индексе.

Кластер

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

Сегменты

Сегменты (Shards) – это составная часть индексов. Каждый сегмент хранит подмножество всех документов в индексе, как показано на рисунке 1.

Рисунок 1 — Схема сегментов индекса

Сегменты используются для равномерного распределения по узлам кластера. Например, индекс размером 400 ГБ может быть слишком большим для одного узла в кластере, но если разделить его на 10 фрагментов по 40 ГБ каждый, Подсистема сможет распределить фрагменты по 10 узлам и управлять каждым сегментом отдельно.

В случае кластера двумя индексами – индекс 1, разделенный на 2 сегмента, и индекс 2, разделенный на 4 сегмента – сегменты распределяются между узлами 1 и 2 таким образом, как показано на рисунке 2.

Рисунок 2 — Распределение сегментов между узлами

Несмотря на то, что каждый сегмент является частью индекса Подсистемы, на самом деле каждый сегмент представляет собой полноценный индекс. Эта деталь важна, потому что каждый экземпляр — это запущенный процесс, который потребляет ресурсы процессора и памяти. Чем больше сегментов, тем лучше, но не всегда. Например, если разделить индекс размером 400 ГБ на 1000 сегментов, это приведет к ненужной нагрузке на кластер. Хорошее практическое правило — ограничивать размер сегмента объемом в 10–50 ГБ.

Основные сегменты и реплики

В Подсистеме сегмент может быть либо основным (первичным), либо репликой (копией) сегмента. По умолчанию Подсистема создает реплику для каждого основного сегмента. Таким образом, если разделить индекс на 10 сегментов, Подсистема создаст 10 реплик. Например, можно рассмотреть кластер, описанный в п. Сегменты. Если добавить по одной реплике для каждого сегмента каждого индекса в кластере, то кластер будет содержать в общей сложности 2 сегмента и 2 реплики для индекса 1 и 4 сегмента и 4 реплики для индекса 2, как показано на рисунке 3.

Рисунок 3 — Распределение сегментов и реплик между узлами

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

Инвертированный индекс

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

Релевантность

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

Отдельные слова в поисковом запросе называются поисковыми терминами. Каждый поисковый термин оценивается по следующим правилам:

  • Поисковый запрос, который чаще встречается в документе, будет иметь более высокий рейтинг – это частота встречаемости термина в рейтинге.
  • Поисковый запрос, который встречается в большем количестве документов, будет иметь более низкий рейтинг – это обратная частота документа в рейтинге.
  • Соответствие в более длинном документе должно оцениваться ниже, чем соответствие в более коротком документе Документ, содержащий полный словарь, будет соответствовать любому слову, но не будет иметь особого отношения к какому-либо конкретному слову. Это соответствует компоненту нормализации по длине в оценке.

Подсистема использует алгоритм ранжирования BM25 для вычисления показателей релевантности документов, а затем возвращает результаты, отсортированные по релевантности.

Жизненный цикл обновления

Жизненный цикл операции обновления состоит из следующих этапов:

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

Журнал транзакций

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

Обновление

Периодически Подсистема выполняет операцию обновления, в ходе которой документы из индекса в памяти записываются в файлы. Эти файлы не являются постоянными, поскольку fsync не выполняется. Обновление делает документы доступными для поиска.

Очистка

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

Слияние

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