Реалізація переіндексації даних Elasticsearch без даунтайму

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.

Розробка та обслуговування будь-яких видів сайтів:

Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Реалізація переіндексації даних Elasticsearch без даунтайму
Складна
~2-3 робочих дні
Часті питання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Реалізація переіндексації даних Elasticsearch без даунтайму

Зміна маппінгу поля — найпоширеніша причина переіндексації. Неможливо змінити тип text на keyword на живому індексі. Неможливо додати новий анализатор до існуючого поля. Рішення: створити новий індекс, перегнати дані через _reindex API, атомарно переключити алиас. Приложення протягом всього процесу продовжує працювати — читає через алиас, який до переключення вказує на старий індекс.

Стратегія blue/green з алиасами

Алиас — абстракція над одним або кількома індексами. Приложення працює з алиасом products, не знаючи фізичної назви індексу.

Початковий стан:

# Перевірити, на що вказує алиас
curl -u elastic:pw "localhost:9200/_alias/products"

# Відповідь:
# { "products_v1": { "aliases": { "products": { "is_write_index": true } } } }

Крок 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" }
    }
  }
}

number_of_replicas: 0 та refresh_interval: -1 при переіндексації — прискорює завантаження даних.

_reindex API

Крок 2 — запустити переіндексацію:

POST _reindex?wait_for_completion=false
{
  "source": {
    "index": "products_v1",
    "size": 1000
  },
  "dest": {
    "index": "products_v2",
    "op_type": "create"
  },
  "conflicts": "proceed"
}

wait_for_completion=false — завдання йде у фон, повертає task_id. Для великих індексів (>1M документів) обов'язково.

op_type: create — пропустити документ, якщо вже існує (важливо для incremental reindex).

conflicts: proceed — при конфліктах версій продовжити, не перериватися.

Моніторинг прогресу:

# По task_id з відповіді
curl -u elastic:pw "localhost:9200/_tasks/oTUltX4IQMOUUVeiohTt8A:12345?pretty"

# Усі активні reindex завдання
curl -u elastic:pw "localhost:9200/_tasks?actions=*reindex&detailed=true&pretty"

Відповідь завдання містить status.created, status.total — можна рахувати відсоток.

Паралельна переіндексація через slices

Для великих індексів — паралельні slices прискорюють у N разів:

POST _reindex?wait_for_completion=false
{
  "source": {
    "index": "products_v1",
    "size": 500
  },
  "dest": {
    "index": "products_v2"
  },
  "slices": "auto"
}

slices: auto — автоматично визначає кількість срізів (за кількістю шардів джерела). Кожний slice обробляється паралельно як окреме завдання. Переіндексація 100M документів з 5 шардами при auto йде в 5 потоків.

Проблема: нові документи під час переіндексації

Поки йде reindex, приложення продовжує записувати в products_v1 (через алиас). Нові та оновлені документи не потрапляють у products_v2.

Рішення — incremental sync після основної переіндексації:

POST _reindex?wait_for_completion=false
{
  "source": {
    "index": "products_v1",
    "query": {
      "range": {
        "updated_at": {
          "gte": "2024-01-15T00:00:00",
          "lte": "now"
        }
      }
    }
  },
  "dest": {
    "index": "products_v2",
    "op_type": "index",
    "version_type": "external"
  }
}

version_type: external — використовувати _version поле для розв'язання конфліктів. Старі документи не перезапишуть нові.

Для цього в маппінгу повинно бути поле updated_at з датою оновлення. Без нього incremental reindex складний.

Атомарне переключення алиаса

Після завершення переіндексації та incremental sync:

# 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"
      }
    }
  ]
}

Операція атомарна — в момент переключення нема стану, коли алиас не вказує на нічого. Запити під час переключення не втрачаються.

Трансформація даних при переіндексації

Reindex підтримує Painless скрипти для трансформації:

POST _reindex
{
  "source": {
    "index": "products_v1"
  },
  "dest": {
    "index": "products_v2"
  },
  "script": {
    "source": """
      // Розділити 'full_name' на 'first_name' та 'last_name'
      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"
  }
}

План відкату

Якщо після переключення виявлено проблеми — откат за секунди:

POST _aliases
{
  "actions": [
    {
      "add": {
        "index": "products_v1",
        "alias": "products",
        "is_write_index": true
      }
    },
    {
      "remove": {
        "index": "products_v2",
        "alias": "products"
      }
    }
  ]
}

Не видаляйте products_v1 відразу — тримайте 24–48 годин для можливості відкату. Потім видаліть, щоб звільнити місце.

Pipeline-переіндексація через ingest

Для збагачення даних при переіндексації — через ingest pipeline:

PUT _ingest/pipeline/enrich-products
{
  "processors": [
    {
      "set": {
        "field": "reindexed_at",
        "value": "{{_ingest.timestamp}}"
      }
    },
    {
      "uppercase": {
        "field": "sku",
        "ignore_missing": true
      }
    }
  ]
}

POST _reindex
{
  "source": { "index": "products_v1" },
  "dest": {
    "index": "products_v2",
    "pipeline": "enrich-products"
  }
}

Таймлайн

Переіндексація з простою зміною маппінгу — 1 робочий день (планування, запуск, моніторинг, переключення). Складний сценарій з трансформацією даних, інкрементальною синхронізацією та тестуванням — 2–3 дні. Для індексів > 100 млн документів — додатково час на саме виконання reindex (6–24 години залежно від залізо).