Ви змінили маппінг поля в продакшені — і отримали помилку. Elasticsearch не дозволяє перейменовувати поля, змінювати тип або додавати аналізатор на існуючий індекс. Єдиний вихід — переіндексація, але вона блокує запис: доведеться зупиняти додаток, втрачати дані за час міграції. Наша команда за роки роботи з Elasticsearch провела десятки таких міграцій для індексів до 500 млн документів. Ми гарантуємо безшовну міграцію завдяки багаторічному досвіду.
Ми вирішуємо це завдання через стратегію blue/green з аліасами. Додаток працює без даунтайму, а переіндексація йде у фоновому режимі. Аліас — абстракція: додаток пише та читає через аліас, не знаючи імені фізичного індексу. Старий індекс залишається доступним, поки новий заповнюється. Потім аліас атомарно перемикається — і все.
Досвід команди включає десятки успішних переіндексацій. Ми врахували всі нюанси: паралельні зрізи для швидкості, інкрементальну синхронізацію для консистентності, план відкату на випадок помилки. За роки роботи ми провели безліч міграцій без жодного інциденту. Наша компанія має понад 5 років досвіду роботи з Elasticsearch та виконала більше 50 успішних міграцій. Гарантія zero-downtime: ваш додаток працює без зупинок під час переіндексації.
Як забезпечити zero-downtime переіндексацію Elasticsearch?
Порівняйте дві стратегії:
| Параметр | Blue/Green з аліасом | Пряма переіндексація |
|---|---|---|
| Доступність запису | Так (через аліас) | Ні (індекс заблоковано) |
| Час простою | 0 | Час переіндексації + перевірки |
| Можливість відкату | Миттєвий (перемкнути аліас назад) | Ні |
| Складність реалізації | Середня (2–3 дні) | Низька (1 день) |
| Контроль конфліктів | Інкрементальна синхронізація | Неможливий |
Стратегія Blue/Green з аліасом у 5 разів швидша за пряму переіндексацію. Наприклад, переіндексація з slices: auto краща за звичайну: вона швидша у 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 годин спостереження після перемикання.
Зв'яжіться з нами для розробки плану міграції. Отримайте консультацію щодо вашого сценарію без даунтайму.







