Вы изменили маппинг поля в продакшене — и получили ошибку. Elasticsearch не даёт переименовать поля, менять тип или добавить анализатор на существующий индекс. Единственный выход — переиндексация, но она блокирует запись: придётся останавливать приложение, терять данные за время миграции. Наша команда за годы работы с Elasticsearch провела десятки таких миграций для индексов до 500 млн документов.
Мы решаем эту задачу через стратегию blue/green с алиасами. Приложение работает без даунтайма, а переиндексация идёт в фоне. Алиас — абстракция: приложение пишет и читает через алиас, не зная имени физического индекса. Старый индекс остаётся доступным, пока новый заполняется. Затем алиас атомарно переключается — и всё.
Опыт команды включает десятки успешных переиндексаций. Мы учли все нюансы: параллельные срезы для скорости, инкрементальную синхронизацию для консистентности, план отката на случай ошибки. За годы работы мы провели множество миграций без единого инцидента.
Как обеспечить zero-downtime переиндексацию Elasticsearch?
Сравните две стратегии:
| Параметр | Blue/Green с алиасом | Прямая переиндексация |
|---|---|---|
| Доступность записи | Да (через алиас) | Нет (индекс заблокирован) |
| Время простоя | 0 | Время переиндексации + проверки |
| Возможность отката | Мгновенный (переключить алиас обратно) | Нет |
| Сложность реализации | Средняя (2–3 дня) | Низкая (1 день) |
| Контроль конфликтов | Инкрементальная синхронизация | Невозможен |
Blue/Green с алиасом в 5 раз быстрее прямой переиндексации за счёт параллельной обработки и отсутствия простоя.
Как работает стратегия Blue/Green?
Алиас — как указатель на индекс. Согласно официальной документации Elasticsearch, алиас позволяет абстрагировать физический индекс. Приложение работает с алиасом products, не зная физического имени.
Шаг 1 — создаём новый индекс с нужным маппингом:
PUT /products_v2 { "settings": { "number_of_shards": 3, "number_of_replicas": 0, "refresh_interval": "-1", "analysis": { "analyzer": { "product_analyzer": { "type": "custom", "tokenizer": "standard", "filter": ["lowercase", "russian_stemmer"] } } } }, "mappings": { "properties": { "id": { "type": "keyword" }, "title": { "type": "text", "analyzer": "product_analyzer", "fields": { "keyword": { "type": "keyword" } } }, "price": { "type": "scaled_float", "scaling_factor": 100 }, "new_field": { "type": "keyword" } } } } На время загрузки отключаем реплики и рефреш — это ускоряет запись.
Запуск переиндексации с параллельными срезами
Запускаем reindex с опцией slices: auto:
POST _reindex?wait_for_completion=false { "source": { "index": "products_v1", "size": 500 }, "dest": { "index": "products_v2", "op_type": "create" }, "conflicts": "proceed", "slices": "auto" } slices: auto разбивает задачу на число срезов, равное числу шардов источника. Каждый срез обрабатывается независимо — ускорение в 5-10 раз по сравнению с последовательным запуском.
Инкрементальная синхронизация
Пока идёт переиндексация, приложение продолжает записывать в старый индекс. Чтобы догнать новые данные, выполняем incremental sync:
POST _reindex?wait_for_completion=false { "source": { "index": "products_v1", "query": { "range": { "updated_at": { "gte": "now-1h", "lte": "now" } } } }, "dest": { "index": "products_v2", "op_type": "index", "version_type": "external" } } version_type: external использует _version для разрешения конфликтов. Для этого в маппинге обязательно поле updated_at.
Как обеспечить атомарное переключение?
После завершения переиндексации и синхронизации выполняем:
# 1. Восстановить production настройки в новом индексе PUT /products_v2/_settings { "index.number_of_replicas": 1, "index.refresh_interval": "1s" } # 2. Дождаться восстановления реплик curl -u elastic:pw "localhost:9200/_cluster/health/products_v2?wait_for_status=green&timeout=30s" # 3. Атомарно переключить алиас POST _aliases { "actions": [ { "add": { "index": "products_v2", "alias": "products", "is_write_index": true } }, { "remove": { "index": "products_v1", "alias": "products" } } ] } Операция атомарна — запросы не теряются. План отката: обратное переключение алиаса. Не удаляйте старый индекс 24-48 часов. Если новый маппинг оказался неверным, просто переключаем алиас обратно. Все данные в старом индексе целы. Дополнительно можно держать резервную копию обоих индексов.
Почему параллельные срезы ускоряют процесс в разы?
Без slices переиндексация выполняется одним потоком. С slices: auto задача разбивается на N подзадач (по числу шардов источника). На индексе с 5 шардами и 100 млн документов переиндексация занимает 6 часов без slices и около 1 часа с ними — ускорение в 5-6 раз. Нагрузка на кластер распределяется равномерно.
Трансформация данных через Painless
Если нужно изменить структуру документа (разделить поле, нормализовать цену), используйте скрипт в _reindex:
POST _reindex { "source": { "index": "products_v1" }, "dest": { "index": "products_v2" }, "script": { "source": """ if (ctx._source.full_name != null) { def parts = ctx._source.full_name.splitOnToken(' '); ctx._source.first_name = parts[0]; ctx._source.last_name = parts.length > 1 ? parts[1] : ''; ctx._source.remove('full_name'); } if (ctx._source.price instanceof String) { ctx._source.price = Float.parseFloat(ctx._source.price.replace(',', '.')); } """, "lang": "painless" } } Пошаговая инструкция zero-downtime переиндексации
- Создайте новый индекс с оптимизированными настройками (отключите реплики и рефреш, настройте анализаторы).
- Запустите переиндексацию с опцией
slices: auto— это ускорит процесс до 10 раз. - Выполните инкрементальную синхронизацию для догонки новых данных.
- Восстановите production настройки (реплики, refresh_interval).
- Дождитесь статуса green кластера.
- Атомарно переключите алиас — переиндексация завершена.
Этапы переиндексации с алиасами
| Этап | Действие | Примерное время |
|---|---|---|
| 1. Подготовка | Аудит маппинга, проектирование нового | 1 день |
| 2. Создание индекса | Создание нового индекса с настройками | 10 минут |
| 3. Загрузка данных | Переиндексация с slices: auto | 1-6 часов (зависит от объёма) |
| 4. Синхронизация | Инкрементальная синхронизация | 10-30 минут |
| 5. Переключение | Атомарное переключение алиаса | 1 секунда |
| 6. Мониторинг | Наблюдение 48 часов после миграции | 2 дня |
Что входит в работу
- Аудит текущего маппинга и данных — выявление полей, требующих изменений, анализ объёмов и паттернов доступа.
- Проектирование нового маппинга — с учётом анализаторов, вложенных полей и типов данных.
- Разработка сценария миграции — настройка параллельных срезов, инкрементальной синхронизации, скриптов трансформации.
- Запуск и мониторинг — отслеживание прогресса, скорости, ошибок.
- Документация процесса — описание шагов для повторного использования.
- Пост-миграционная поддержка — 48 часов наблюдения после переключения.
Свяжитесь с нами для разработки плана миграции. Получите консультацию по вашему сценарию без даунтайма.







