Ви змінили маппінг поля в продакшені — і отримали помилку. 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 годин спостереження після перемикання.
Зв'яжіться з нами для розробки плану міграції. Отримайте консультацію щодо вашого сценарію без даунтайму.







