Кластер, ноды, шарды и реплики

Один Elasticsearch — это кластер

Когда вы запускаете ES, вы запускаете кластер — даже если он состоит из одного процесса. Кластер — это группа нод с единым именем (cluster.name в конфиге). Снаружи кластер выглядит как один сервис: один адрес, один API. То, как именно данные распределены внутри, — детали, которые ES скрывает за абстракцией.

Посмотреть состояние кластера:

GET /_cluster/health

Нода — один процесс ES

Нода (node) — это один запущенный процесс Elasticsearch. Обычно нода = один сервер или один Docker-контейнер. Ноды бывают разных ролей:

  • master — управляет метаданными кластера: кто живой, где какие шарды. Сами данные не хранит.
  • data — хранит шарды и выполняет поисковые запросы.
  • coordinating — принимает запрос от клиента, рассылает его на нужные ноды и мёрджит ответ. Любая нода неявно выполняет эту роль.

На старте все роли берёт одна нода. В продакшне они разделяются.

graph TD Client[Клиент curl/Kibana] --> CN subgraph Cluster[Кластер] CN[Coordinating Node] subgraph Node1[Нода 1] P0[Шард 0 primary] R1[Шард 1 replica] end subgraph Node2[Нода 2] P1[Шард 1 primary] R2[Шард 2 replica] end subgraph Node3[Нода 3] P2[Шард 2 primary] R0[Шард 0 replica] end CN --> P0 CN --> P1 CN --> P2 end
graph TD
    Client[Клиент curl/Kibana] --> CN
    subgraph Cluster[Кластер]
        CN[Coordinating Node]
        subgraph Node1[Нода 1]
            P0[Шард 0 primary]
            R1[Шард 1 replica]
        end
        subgraph Node2[Нода 2]
            P1[Шард 1 primary]
            R2[Шард 2 replica]
        end
        subgraph Node3[Нода 3]
            P2[Шард 2 primary]
            R0[Шард 0 replica]
        end
        CN --> P0
        CN --> P1
        CN --> P2
    end
Кластер из трёх нод: primary-шарды и реплики распределены между нодами, coordinating-нода принимает запрос клиента и маршрутизирует его

Индекс — не единый файл, а набор шардов

Вот главная идея: индекс физически делится на шарды. Каждый шард — это полноценный, самостоятельный индекс Apache Lucene. Шард живёт на конкретной ноде, умеет принимать записи и отвечать на поисковые запросы.

По умолчанию (с ES 7.0) у нового индекса один primary-шард. Для большего объёма данных число задают при создании:

PUT /products
{
  "settings": {
    "number_of_shards": 3,
    "number_of_replicas": 1
  }
}

Число primary-шардов (number_of_shards) нельзя изменить после создания индекса.

Проверь себя
Вы создали индекс с тремя primary-шардами. Через неделю данных стало в разы больше и понадобилось пять шардов. Почему нельзя просто поменять `number_of_shards` с 3 на 5? Что именно сломается — попробуйте объяснить своими словами.

Primary и replica шарды

Каждый шард существует в двух ролях.

Primary shard — принимает все запросы на запись. Каждый документ записывается ровно в один primary-шард.

Replica shard — точная копия primary-шарда, размещённая на другой ноде. Реплики решают две задачи:

1. Отказоустойчивость: если нода с primary упадёт, ES повысит реплику до primary — данные не теряются.

2. Пропускная способность на чтение: поисковые запросы ES может направить на любую реплику, не только на primary.

Жёсткое правило: primary и его реплика никогда не живут на одной ноде. Поэтому на кластере из одной ноды реплики останутся в статусе UNASSIGNED — некуда их разместить. Для разработки это нормально; в продакшне нужно минимум две ноды.

Важно: number_of_replicas можно изменить в любой момент, даже на живом индексе.

Проверь себя
Кластер из одной ноды, индекс `logs` с `number_of_shards: 1, number_of_replicas: 1`. Что случится с репликой и каким будет статус кластера?

Как документ попадает в нужный шард: формула роутинга

Когда ES получает новый документ, он должен решить, в какой primary-шард его записать. Для этого используется формула:

$$\text{shard} = \text{hash}(\_id) \bmod N_{\text{primary}}$$

Где $N_{\text{primary}}$ — количество primary-шардов индекса.

Именно поэтому нельзя менять число primary-шардов постфактум. Допустим, индекс имел $N_{\text{primary}} = 3$ и документ с _id = "abc" попал в шард $\text{hash}(\text{abc}) \bmod 3 = 1$. После изменения на $N_{\text{primary}} = 5$ та же формула даст $\text{hash}(\text{abc}) \bmod 5 = 4$ — ES будет искать документ в шарде 4, а он лежит в шарде 1. Данные окажутся недоступны.

Если перешардировать всё же нужно — создают новый индекс с нужным числом шардов и переносят данные через _reindex.

Здоровье кластера: green, yellow, red

ES следит за каждым шардом и выражает состояние тремя цветами:

СтатусЧто означает
🟢 greenВсе primary и все реплики размещены
🟡 yellowВсе primary размещены, хотя бы одна реплика — нет
🔴 redХотя бы один primary не размещён; часть данных недоступна

Пример — запрос и ответ для одной ноды:

GET /_cluster/health?pretty
{
  "cluster_name": "my-cluster",
  "status": "yellow",
  "number_of_nodes": 1,
  "active_primary_shards": 1,
  "active_shards": 1,
  "unassigned_shards": 1
}
Проверь себя
Кластер перешёл в статус red. Это значит, что ES полностью недоступен и все запросы вернут ошибку?

Как это выглядит на практике

Допустим, индекс products создан с number_of_shards: 3, number_of_replicas: 1 на кластере из трёх нод. ES разместит три primary-шарда (по одному на ноду) и три реплики (каждая — на ноде, отличной от primary). Итого 6 шардов, равномерно распределённых по трём нодам.

При поисковом запросе одна из нод становится coordinating: рассылает подзапрос на все три шарда (primary или реплика — без разницы), собирает лучшие результаты от каждого и возвращает клиенту.

Посмотреть распределение шардов:

GET /_cat/shards/products?v

В ответе — список с колонками: индекс, номер шарда, роль (p — primary, r — replica), статус, нода.

Сколько шардов нужно

Один шард хорошо работает для данных объёмом примерно до 50 ГБ. Если объём больше — делите. Но избыток шардов вреден: каждый потребляет RAM и файловые дескрипторы, добавляет накладные расходы при поиске. «Больше шардов = быстрее» — распространённое заблуждение.


Быстрое повторение
Зачем индекс делится на шарды?
Быстрое повторение
Что такое нода в контексте Elasticsearch?
Быстрое повторение
Что такое кластер в Elasticsearch?

См. также