Кластер, ноды, шарды и реплики
Один 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Индекс — не единый файл, а набор шардов
Вот главная идея: индекс физически делится на шарды. Каждый шард — это полноценный, самостоятельный индекс Apache Lucene. Шард живёт на конкретной ноде, умеет принимать записи и отвечать на поисковые запросы.
По умолчанию (с ES 7.0) у нового индекса один primary-шард. Для большего объёма данных число задают при создании:
PUT /products
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1
}
}Число primary-шардов (number_of_shards) нельзя изменить после создания индекса.
Primary и replica шарды
Каждый шард существует в двух ролях.
Primary shard — принимает все запросы на запись. Каждый документ записывается ровно в один primary-шард.
Replica shard — точная копия primary-шарда, размещённая на другой ноде. Реплики решают две задачи:
1. Отказоустойчивость: если нода с primary упадёт, ES повысит реплику до primary — данные не теряются.
2. Пропускная способность на чтение: поисковые запросы ES может направить на любую реплику, не только на primary.
Жёсткое правило: primary и его реплика никогда не живут на одной ноде. Поэтому на кластере из одной ноды реплики останутся в статусе UNASSIGNED — некуда их разместить. Для разработки это нормально; в продакшне нужно минимум две ноды.
Важно: number_of_replicas можно изменить в любой момент, даже на живом индексе.
Как документ попадает в нужный шард: формула роутинга
Когда ES получает новый документ, он должен решить, в какой 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
}Как это выглядит на практике
Допустим, индекс 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 и файловые дескрипторы, добавляет накладные расходы при поиске. «Больше шардов = быстрее» — распространённое заблуждение.