Москва: проверенные б/у ноутбуки с гарантией и проверкой перед оплатой
+7 906 722-94-45

Главная → Статьи → Индексация данных для поиска: синхронизация с источником

Индексация данных для поиска и синхронизация с базой

Синхронизация поискового индекса с источником: полная переиндексация, инкрементальное обновление, CDC, отставание индекса и алиасы.

Прямой ответ

Поисковый индекс — производная структура. Источник данных остаётся системой записи, а индекс восстанавливается из источника, поэтому задача сводится к поддержанию соответствия между ними.

Три способа поддержания соответствия.

Полная переиндексация. Индекс перестраивается целиком из источника. Применяется при изменении маппинга и анализатора, а также как восстановление после сбоя.

Инкрементальное обновление. В индекс пишутся только изменённые документы. Требует определения изменения: по отметке времени обновления либо по журналу изменений базы.

Журнал изменений (CDC). Изменения читаются из журнала транзакций базы и применяются к индексу; о механизме — в статье про change data capture.

Способ Отставание Стоимость Когда применять
Полная переиндексация Часы Высокая Изменение маппинга, восстановление
По отметке обновления Минуты Низкая Простая схема, допустимое отставание
CDC по журналу Секунды Средняя Низкое отставание, большой объём
Запись при изменении Секунды Низкая Один сервис-владелец данных

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

Переиндексация без простоя выполняется через алиас:

import httpx

ES = ""

httpx.put(f"{ES}/products-v2", json={
    "mappings": {"properties": {"title": {"type": "text"}, "brand": {"type": "keyword"}}}
})

# перенос данных в products-v2 ...

httpx.post(f"{ES}/_aliases", json={"actions": [
    {"remove": {"index": "products-v1", "alias": "products"}},
    {"add": {"index": "products-v2", "alias": "products"}},
]})

Приложение обращается к алиасу, поэтому переключение индекса не требует изменения кода.

Отставание индекса и его последствия

Индекс не обновляется одновременно с источником, поэтому между ними существует окно расхождения. Величина окна определяет допустимые сценарии использования.

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

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

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

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

Отдельная задача — обнаружение расхождения. Периодическая сверка числа документов в источнике и индексе выявляет пропущенные обновления; о методике — в статье про отслеживание прогресса переноса.

При использовании журнала транзакций отставание определяется задержкой чтения журнала и скоростью применения изменений; о логической репликации — в статье про репликацию и миграцию PostgreSQL.

Практика: организация синхронизации индекса

1. Определяйте источник записи явно. Индекс не используется как источник истины, поэтому восстановление выполняется из базы.

2. Разделяйте полный и инкрементальный перенос. Полная переиндексация выполняется по расписанию либо при изменении схемы, инкрементальная — постоянно.

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

4. Проверяйте статус индексации. Ответ с идентификатором задачи означает принятие, а не завершение записи.

5. Обрабатывайте ошибки индексации отдельно от ошибок записи. Сбой записи в индекс не должен откатывать транзакцию в базе.

6. Ведите учёт отставания. Разница между временем последнего изменения в источнике и временем последней индексации — ключевая метрика.

7. Сверяйте объёмы периодически. Совпадение числа документов не гарантирует совпадения содержимого, но выявляет пропущенные записи.

8. Планируйте переиндексацию по времени. Перестройка индекса создаёт нагрузку, поэтому выполняется в период низкой активности.

Рекомендации:

  1. Не храните в индексе данные, которых нет в источнике. Восстановление индекса из источника теряет такие данные.
  2. Проверяйте актуальные значения при выдаче. Цена, наличие и права доступа читаются из источника, а не из индекса.
  3. Учитывайте стоимость полного переноса. Переиндексация миллионов документов занимает часы и создаёт нагрузку на источник.
  4. Используйте исходящую очередь для надёжности. Запись события об изменении в той же транзакции, что и изменение данных, устраняет потерю обновлений.
  5. Документируйте допустимое отставание. Значение определяется сценарием использования и фиксируется в требованиях.

Практический сценарий: пропавшие из поиска документы после сбоя

Контекст: часть товаров перестала находиться в поиске, хотя в базе присутствовала.

  1. Диагностика. Сверка числа документов показала расхождение: в источнике на несколько тысяч записей больше, чем в индексе. Расхождение накопилось за период сбоя сервиса индексации.
  2. Причина. Обновление индекса выполнялось в том же процессе, что и запись в базу, без очереди и повторных попыток. Сбой сервиса приводил к потере обновлений, а механизм восстановления отсутствовал.
  3. Действия. (а) Создали новый индекс с актуальным маппингом и выполнили полную переиндексацию из источника; (б) переключили алиас на новый индекс после проверки объёма; (в) добавили исходящую очередь: событие об изменении записывается в той же транзакции, что и изменение данных, а отдельный процесс применяет события к индексу; (г) включили повторные попытки при сбое индексации и очередь недоставленных сообщений для повторяющихся ошибок; (д) добавили метрику отставания и периодическую сверку объёмов.
  4. Результат. Потеря обновлений исключена записью события в транзакции, а расхождение обнаруживается метрикой до обращения пользователей.

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

FAQ

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

Как обнаружить расхождение между базой и индексом? Периодической сверкой числа документов и выборочной сверкой содержимого по идентификаторам.

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

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

Источники: Elasticsearch index aliases, PostgreSQL logical decoding, Debezium documentation — ссылки в шапке.