Переиндексирование данных в Solr

Переиндексирование в Solr — это процесс удаления всего содержимого индекса Solr с последующей записью данных из источника данных (базы данных, файла или другого хранилища) для создания нового индекса. При выполнении переиндексирования важно, чтобы все документы и сегменты Lucene были удалены для избежания конфликтов при повторном воссоздании индекса.

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

Случаи, когда требуется переиндексирование

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

Обновление схемы

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

Обновление схемы Solr-коллекции (например, изменение типов полей, добавление новых полей или изменение логики анализа) почти всегда требует полного переиндексирования.

Это требование обусловлено архитектурой поискового движка Lucene. Сегменты Lucene, в которых хранятся "сырые" данные, являются неизменяемыми, то есть после записи сегмента на диск он не может быть изменен. Сегменты можно добавлять, объединять, удалять, но не изменять. Сегменты Lucene слабо связаны с Solr-схемой, поскольку схема Solr — это концепция только Solr. Файл схемы лишь указывает Solr, как данные должны быть записаны в индекс Lucene и как их запросить в дальнейшем. После записи данных в индекс Lucene схема Solr не управляет хранимыми структурами данных.

Обновление данных

Если исходные данные были значительно изменены (например, в результате массовых обновлений или исправлений), то более эффективным будет переиндексирование всего набора данных вместо применения инкрементных обновлений.

Поврежденный индекс

Если индекс Solr поврежден или некоторые документы проиндексированы неправильно, переиндексирование может помочь вернуть индекс в рабочее состояние.

Улучшение производительности

Изменения настроек индексирования (токенизация, фильтры, анализ) или оптимизаций могут потребовать переиндексирования для вступления в силу. Здесь также следует руководствоваться правилом: если обновляются настройки, связанные с записью данных в индекс, переиндексирование необходимо; если обновляется лишь логика выполнения запросов — переиндексирование не обязательно.

Стратегии переиндексирования

Существует две основные стратегии переиндексирования, описанные ниже. Обе стратегии позволяют гарантировать, что индекс Lucene полностью пуст, прежде чем в него будут повторно помещены данные.

Удаление всех документов

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

$ curl http://ka-adh-1.ru-central1.internal:8983/solr/test_collection/update?commit=true -H "Content-Type: application/json" --data-binary '{"delete": { "query": "*:*" }}'

Где:

  • ka-adh-1.ru-central1.internal — имя хоста, на котором запущен сервер Solr;

  • test_collection — имя коллекции, которую нужно очистить.

Пример ответа Solr-сервера:

{
  "responseHeader":{
    "rf":1,
    "status":0,
    "QTime":40}}
РЕКОМЕНДАЦИЯ
После операции удаления еще раз выполните поисковый запрос, чтобы убедиться, что все документы были удалены из коллекции. Это гарантирует, что сегменты индекса Lucene также были удалены.

Чтобы убедиться, что в индексе не осталось сегментов Lucene, проверьте директорию {SOLR_HOME}/<collection_name>_*/data/index/ коллекции и убедитесь, что в ней нет файлов сегментов. Это необходимо выполнить для каждого шарда и каждой реплики вашего Solr-кластера. Чтобы найти шарды и реплики Lucene, принадлежащие данной коллекции, воспользуйтесь Solr web UI, как показано на рисунке.

Расположение шардов Solr
Расположение шардов Solr
Расположение шардов Solr
Расположение шардов Solr

Затем подключитесь к каждому хосту, на котором хранятся шарды и реплики, и выполните команду:

$ ls -l /srv/solr/server/test_collection_*/data/index

Где:

  • /srv/solr/server/ — директория по умолчанию (SOLR_HOME), где Solr хранит данные коллекций;

  • test_collection — имя коллекции.

Следующий вывод показывает, что данные коллекции были удалены и индекс пуст:

[admin@ka-adh-3 ~]$ ls -l /srv/solr/server/test_collection_*/data/index
total 4
-rw-r--r--. 1 solr solr 135 Oct 11 12:37 segments_7
-rw-r--r--. 1 solr solr   0 Oct 11 09:00 write.lock

Файлы segments_N и write.lock являются вспомогательными и не должны удаляться во время переиндексирования. Если директория data/index/ вашей коллекции находится в таком состоянии, то ваша коллекция готова к переиндексированию.

ВАЖНО
Не удаляйте вручную файлы в директории data/index/, так как это неизбежно приведет к повреждению индекса.

Основным недостатком этого подхода является возможное время простоя или некорректные результаты поиска при повторной записи данных в индекс. Следующая описанная стратегия помогает обойти эту проблему.

Индексирование в другую коллекцию

Другой подход к переиндексированию предполагает использование алиасов коллекций (collection alias), что позволяет перенаправлять запросы от клиентских приложений в другую коллекцию через алиас, избегая простоев.

При таком подходе процесс переиндексирования состоит из следующих шагов:

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

  2. Индексируйте свежие данные в новую коллекцию.

  3. После индексирования создайте алиас, который будет перенаправлять клиентские запросы к новой коллекции. Вы можете создать алиас для коллекции с помощью Solr web UI, как показано на рисунке ниже.

    Создание алиаса для коллекции
    Создание алиаса
    Создание алиаса для коллекции
    Создание алиаса
  4. Удалите старую коллекцию как ненужную.

Команда REINDEXCOLLECTION

Solr предоставляет команду REINDEXCOLLECTION, которая позволяет выполнить индексирование коллекции, используя данные из исходной коллекции.

ПРИМЕЧАНИЕ
При использовании команды REINDEXCOLLECTION могут теряться данные, так как команда копирует только данные со значением полей stored=true. Рекомендуется не удалять исходную коллекцию сразу после переиндексирования, а сохранить ее в качестве бэкапа на случай потери некоторых данных.

Чтобы запустить команду, отправьте GET-запрос на URL /admin/collections?action=REINDEXCOLLECTION&name=<collection_name>. После запуска команды исходная коллекция переходит в read-only режим, чтобы обеспечить корректную обработку всех исходных документов. Для каждой исходной коллекции может быть запущена только одна операция REINDEXCOLLECTION. Вы можете принудительно завершить длительные, зависшие или неудачные операции с помощью опции abort, которая также удаляет частично скопированные документы. Если при копировании документов в целевую коллекцию произошел сбой, Solr удаляет временные и целевые коллекции, а также отключает режим read-only исходной коллекции.

Параметры команды

Команда REINDEXCOLLECTION принимает следующие параметры в виде параметров запроса URL.

Параметр Описание

name

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

cmd

Указывает операцию, которую необходимо выполнить. Поддерживаются следующие операции:

  • start — запускает процесс переиндексирования (значение по умолчанию).

  • abort — прерывает запущенный или неудачный сеанс переиндексирования. Удаляет частичные результаты, если таковые имеются.

  • status — возвращает информацию о состоянии запущенного сеанса переиндексирования.

target

Имя целевой коллекции. Если не указано, Solr создает коллекцию с уникальным именем и после переиндексирования создает алиас, указывающий на вновь созданную коллекцию, тем самым "изолируя" исходную коллекцию от запросов на чтение и обновление

q

Опциональная строка запроса для выборки документов для переиндексирования. По умолчанию используется значение *:*

fl

Опциональный список полей для переиндексирования. По умолчанию используется значение *

rows

Указывает размер пакета для копирования документов. В зависимости от среднего размера документа большие размеры пакета могут вызывать проблемы с памятью. Значение по умолчанию — 100

configName

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

removeSource

Если указано значение true, удаляет исходную коллекцию после переиндексирования

Примеры использования команды

Чтобы выполнить приведенные ниже примеры, создайте тестовую коллекцию и проиндексируйте тестовый документ, как описано в статье Обзор работы с индексами в Solr.

Пример: запуск REINDEXCOLLECTION с параметрами по умолчанию

 

Следующий запрос запускает процесс переиндексирования исходной коллекции с именем test_collection.

$ curl 'http://localhost:8983/solr/admin/collections?action=REINDEXCOLLECTION&name=test_collection'

Ответ Solr-сервера:

{
  "responseHeader":{
    "status":0,
    "QTime":6453},
  "reindexStatus":{
    "actualSourceCollection":"test_collection",
    "actualTargetCollection":".rx_test_collection_3",
    "alias":"test_collection -> .rx_test_collection_3",
    "checkpointCollection":".rx_ck_test_collection",
    "inputDocs":1,
    "phase":"done",
    "processedDocs":1,
    "state":"finished"}}

Ответ показывает, что Solr создал новую коллекцию .rx_test_collection_3 и алиас test_collection, указывающий на новую коллекцию. Проверьте содержимое новой коллекции, явно указав ее имя в обход алиаса:

$ curl 'http://ka-adh-1.ru-central1.internal:8983/solr/.rx_test_collection_3/select?indent=true&q.op=OR&q=*%3A*'

Ответ содержит тестовый документ, скопированный из исходной коллекции.

{
  "responseHeader":{
    "zkConnected":true,
    "status":0,
    "QTime":0,
    "params":{
      "q":"*:*",
      "indent":"true",
      "q.op":"OR"}},
  "response":{"numFound":1,"start":0,"numFoundExact":true,"docs":[
      {
        "txn_id":[1],
        "txn_date":["2024-01-02T00:00:00Z"],
        "txn_value":[75.0],
        "comment":["The first transaction."],
        "id":"1",
        "acc_id":[1001],
        "_version_":1812905933055983616}]
  }}

Исходная коллекция (test_collection) не удалена, однако теперь Solr направляет все запросы на чтение/обновление к новой коллекции через алиас.

Пример: реиндексирование определенных данных

 

Следующий запрос запускает процесс переиндексирования с указанием параметров выборки данных, подлежащих копированию в целевую коллекцию.

$ curl 'http://localhost:8983/solr/admin/collections?action=REINDEXCOLLECTION&name=test_collection&q=txn_id:1&fl=id,txn_id,txn_value,acc_id&target=test_collection2'

Ответ Solr-сервера:

{
  "responseHeader":{
    "status":0,
    "QTime":6215},
  "reindexStatus":{
    "actualSourceCollection":"test_collection",
    "actualTargetCollection":"test_collection2",
    "checkpointCollection":".rx_ck_test_collection",
    "inputDocs":1,
    "phase":"done",
    "processedDocs":1,
    "state":"finished"}}

Проверьте содержимое целевой коллекции:

$ curl 'http://ka-adh-1.ru-central1.internal:8983/solr/test_collection2/select?indent=true&q.op=OR&q=*%3A*'

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

{
  "responseHeader":{
    "zkConnected":true,
    "status":0,
    "QTime":0,
    "params":{
      "q":"*:*",
      "indent":"true",
      "q.op":"OR"}},
  "response":{"numFound":1,"start":0,"numFoundExact":true,"docs":[
      {
        "txn_id":[1],
        "txn_value":[75.0],
        "id":"1",
        "acc_id":[1001],
        "_version_":1812908971102568448}]
  }}
Нашли ошибку? Выделите текст и нажмите Ctrl+Enter чтобы сообщить о ней