Сколько шардов должно быть в кластере Elasticsearch?

elasticsearch logo Elasticsearch

Elasticsearch - это очень универсальная платформа, которая поддерживает множество вариантов использования и обеспечивает большую гибкость в организации данных и стратегиях репликации. Однако эта гибкость иногда затрудняет определение того, как лучше организовать данные в индексы и шарды, особенно если вы новичок в Elastic Stack. Хотя неоптимальный выбор не обязательно вызовет проблемы в начале работы, он может привести к проблемам с производительностью по мере роста объемов данных. Чем больше данных хранит кластер, тем сложнее становится устранить проблему, поскольку иногда может потребоваться переиндексация больших объемов данных.

Эмпирическое правило "Стремитесь к 20 или менее шардам на ГБ памяти кучи" было отменено в версии 8.3.

Когда мы сталкиваемся с пользователями, испытывающими проблемы с производительностью, нередко это можно отнести к проблемам, связанным со способом индексирования данных и количеством осколков в кластере. Это особенно верно для примеров использования, включающих многопользовательскую работу и/или использование индексов, основанных на времени. При обсуждении этих вопросов с пользователями, как лично на мероприятиях или встречах, так и на нашем форуме, одними из самых распространенных являются вопросы "Сколько шардов я должен иметь?" и "Какого размера должны быть мои шарды?".

Что такое шард?

Данные в Elasticsearch организованы в индексы. Каждый индекс состоит из одного или нескольких шардов. Каждый шард - это экземпляр индекса Lucene, который можно рассматривать как автономную поисковую систему, индексирующую и обрабатывающую запросы для подмножества данных в кластере Elasticsearch.

По мере записи данных в шард они периодически публикуются в новые неизменяемые сегменты Lucene на диске, и именно в это время они становятся доступными для запросов. Это называется обновлением.

По мере роста числа сегментов они периодически объединяются в более крупные сегменты. Этот процесс называется объединением. Поскольку все сегменты неизменяемы, это означает, что используемое дисковое пространство обычно колеблется во время индексирования, так как новые, объединенные сегменты должны быть созданы до того, как замененные ими сегменты будут удалены. Слияние может быть достаточно ресурсоемким, особенно в отношении дискового ввода-вывода.

Шард - это единица, с помощью которой Elasticsearch распределяет данные по кластеру. Скорость, с которой Elasticsearch может перемещать шарды при ребалансировке данных, например, после сбоя, зависит от размера и количества шардов, а также от производительности сети и дисков.

Избегайте очень больших шардов, так как это может негативно повлиять на способность кластера восстанавливаться после сбоев. Не существует фиксированного ограничения на размер шардов, но часто упоминается размер шарда в 50 ГБ как предел, который работает в различных случаях.

Индексирование по периоду хранения

Поскольку сегменты неизменяемы, обновление документа требует, чтобы Elasticsearch сначала нашел существующий документ, затем пометил его как удаленный и добавил обновленную версию. Удаление документа также требует, чтобы документ был найден и помечен как удаленный. По этой причине удаленные документы будут продолжать занимать дисковое пространство и некоторые системные ресурсы до тех пор, пока они не будут удалены, что может потребовать много системных ресурсов.

Elasticsearch позволяет очень эффективно удалять полные индексы непосредственно из файловой системы, без необходимости явного удаления всех записей по отдельности. Это, безусловно, самый эффективный способ удаления данных из Elasticsearch.

Старайтесь использовать индексы, основанные на времени, для управления хранением данных, когда это возможно. Группируйте данные в индексы на основе периода хранения. Индексы на основе времени также позволяют легко изменять количество первичных осколков и реплик с течением времени, поскольку их можно изменить для следующего создаваемого индекса. Это упрощает адаптацию к изменяющимся объемам данных и требованиям.

Являются ли индексы и шарды не бесплатными?

Для каждого индекса Elasticsearch информация о сопоставлениях и состоянии хранится в состоянии кластера. Она хранится в памяти для быстрого доступа. Поэтому наличие большого количества индексов и шардов в кластере может привести к большому состоянию кластера, особенно если сопоставлений много. Его обновление может стать медленным, так как все обновления должны выполняться через один поток, чтобы гарантировать согласованность до того, как изменения будут распределены по кластеру.

Чтобы уменьшить количество индексов и избежать больших и разрастающихся отображений, рассмотрите возможность хранения данных с похожей структурой в одном индексе, а не разбивать их на отдельные индексы в зависимости от того, откуда поступают данные. Важно найти хороший баланс между количеством индексов и шардов, а также размером отображения для каждого отдельного индекса. Поскольку состояние кластера загружается в кучу на каждом узле (включая ведущие), а объем кучи прямо пропорционален количеству индексов, полей на индекс и шардов, важно также следить за использованием кучи на ведущих узлах и убедиться, что они имеют соответствующий размер.

Каждый шард имеет данные, которые должны храниться в памяти и использовать пространство кучи. Сюда входят структуры данных, содержащие информацию на уровне шарда, а также на уровне сегмента, чтобы определить местоположение данных на диске. Размер этих структур данных не является фиксированным и зависит от конкретного случая использования.

Важной характеристикой накладных расходов, связанных с сегментами, является то, что они не строго пропорциональны размеру сегмента. Это означает, что большие сегменты имеют меньшие накладные расходы на объем данных по сравнению с меньшими сегментами. Разница может быть существенной.

Для того чтобы иметь возможность хранить как можно больше данных на одном узле, становится важным управлять использованием кучи и максимально снизить накладные расходы. Чем больше места в куче у узла, тем больше данных и шардов он может обрабатывать.

Поэтому индексы и шарды не являются бесплатными с точки зрения кластера, поскольку для каждого индекса и шарда существует определенный уровень накладных расходов ресурсов.

Советы

  • Маленькие шарды приводят к маленьким сегментам, что увеличивает накладные расходы. Старайтесь, чтобы средний размер шарда составлял не менее нескольких ГБ и не более нескольких десятков ГБ. В случаях использования данных, основанных на времени, часто встречаются шарды размером от 20 до 40 ГБ.
  • Поскольку накладные расходы на один шард зависят от количества и размера сегментов, принудительное объединение меньших сегментов в большие с помощью операции forcemerge может снизить накладные расходы и повысить производительность запросов. В идеале это следует делать после того, как в индекс больше не будут записываться данные. Имейте в виду, что это дорогостоящая операция, которую лучше выполнять в непиковые часы.
  • Количество шардов, которые вы можете разместить на узле, будет пропорционально объему доступной кучи, однако Elasticsearch не устанавливает фиксированного предела. Хорошее правило заключается в том, чтобы количество шардов на узле не превышало 20 на каждый сконфигурированный гигабайт кучи. Таким образом, узел с кучей 30 ГБ должен иметь максимум 600 шардов, но чем ниже этот предел, тем лучше. В целом это поможет кластеру оставаться в хорошем состоянии.

    Начиная с версии 8.3 ElasticSearch значительно сократили использование кучи на шард, тем самым обновив эмпирическое правило. Пожалуйста, следуйте СОВЕТУ ниже для версий Elasticsearch 8.3+.

  • Разрешить 1 кБ кучи на поле на индекс на узлах данных, плюс накладные расходы.
    Точное использование ресурсов каждого сопоставленного поля зависит от его типа, но эмпирическое правило гласит, что на каждое сопоставленное поле на индекс, хранящийся на каждом узле данных, должно приходиться примерно 1 кБ кучи. Вы также должны предусмотреть достаточный объем памяти для базового использования Elasticsearch, а также для вашей рабочей нагрузки, такой как индексирование, поиск и агрегация. Дополнительной кучи в 0,5 ГБ будет достаточно для многих разумных рабочих нагрузок, и вам может понадобиться даже меньше, если ваша рабочая нагрузка очень легкая, в то время как для тяжелых рабочих нагрузок может потребоваться больше.

Например, если узел данных хранит осколки из 1000 индексов, каждый из которых содержит 4000 сопоставленных полей, то вы должны выделить примерно 1000 × 4000 × 1kB = 4GB кучи для полей и еще 0,5GB кучи для рабочей нагрузки и других накладных расходов, и поэтому этому узлу потребуется куча размером не менее 4,5GB.

Как размер шарда влияет на производительность?

В Elasticsearch каждый запрос выполняется в одном потоке на каждом шарде. Однако несколько шардов могут обрабатываться параллельно, как и несколько запросов и агрегаций к одному и тому же шарду.

Это означает, что минимальная задержка запроса при отсутствии кэширования зависит от данных, типа запроса, а также от размера хранилища. Запрос к большому количеству маленьких шардов ускорит обработку каждого шарда, но поскольку в очередь нужно поставить гораздо больше задач и обрабатывать их последовательно, это не обязательно будет быстрее, чем запрос к меньшему количеству больших шардов. Наличие большого количества мелких шардов также может снизить пропускную способность запроса, если имеется несколько одновременных запросов.

Лучший способ определить максимальный размер шарда с точки зрения производительности запросов - провести сравнительный анализ с использованием реалистичных данных и запросов. Всегда проводите сравнительный анализ с запросами и нагрузкой индексирования, репрезентативной той, которую узел должен будет обрабатывать на производстве, поскольку оптимизация под один запрос может дать неверные результаты.

Как управлять размером хранилища?

При использовании индексов, основанных на времени, каждый индекс традиционно ассоциируется с определенным периодом времени. Очень распространены ежедневные индексы, которые часто используются для хранения данных с коротким периодом хранения или большими ежедневными объемами. Они позволяют управлять периодом хранения с хорошей детализацией и легко корректировать изменяющиеся объемы на ежедневной основе. Данные с более длительным периодом хранения, особенно если ежедневные объемы не позволяют использовать ежедневные индексы, часто используют еженедельные или ежемесячные индексы, чтобы сохранить размер шарда. Это уменьшает количество индексов и шардов, которые необходимо хранить в кластере с течением времени.

При использовании индексов на основе времени с фиксированным периодом настройте период, который охватывает каждый индекс, на основе периода хранения и ожидаемых объемов данных, чтобы достичь целевого размера черепка.

Индексы на основе времени с фиксированным временным интервалом хорошо работают, когда объемы данных достаточно предсказуемы и меняются медленно. Если скорость индексирования может быстро меняться, очень сложно поддерживать единый целевой размер черепка.

Для того чтобы лучше справляться с такими сценариями, были введены API Rollover и Shrink. Они добавляют много гибкости в управление индексами и шардами, особенно для индексов, основанных на времени.

API rollover index позволяет указать количество документов, которые должен содержать индекс, и/или максимальный период записи документов в него. Как только один из этих критериев будет превышен, Elasticsearch может инициировать создание нового индекса для записи без простоя. Вместо того чтобы каждый индекс охватывал определенный временной период, теперь можно переключиться на новый индекс при определенном размере, что позволяет легче добиться равномерного размера шарда для всех индексов.

В случаях, когда данные могут обновляться, при использовании этого API больше нет четкой связи между временной меткой события и индексом, в котором оно находится, что может сделать обновление значительно менее эффективным, поскольку каждому обновлению может предшествовать поиск.

Если у вас есть неизменяемые данные, основанные на времени, объемы которых могут значительно меняться с течением времени, рассмотрите возможность использования API rollover index для достижения оптимального размера целевого шарда путем динамического изменения временного периода, который охватывает каждый индекс. Это обеспечивает большую гибкость и помогает избежать слишком больших или слишком маленьких хранилищ, когда объемы непредсказуемы.

API shrink index позволяет сократить существующий индекс в новый индекс с меньшим количеством первичных шардов. Если при индексировании необходимо равномерное распределение шардов по узлам, но в результате получаются слишком маленькие шарды, этот API можно использовать для уменьшения количества первичных шардов, когда индекс больше не индексируется. В результате получатся более крупные шарды, которые лучше подходят для долгосрочного хранения данных.

Если вам нужно, чтобы каждый индекс охватывал определенный период времени, но при этом вы хотите распределить индексирование по большому количеству узлов, рассмотрите возможность использования API shrink для уменьшения количества первичных шардов после того, как индекс перестанет индексироваться. Этот API также можно использовать для уменьшения количества шардов в случае, если вы изначально настроили слишком много шардов.

Выводы

Многие решения о том, как лучше распределить данные по индексам и шардам, зависят от специфики конкретного случая использования, и иногда бывает трудно определить, как лучше применить имеющиеся советы.

Avatar for Gnostis
Gnostis
Добавить комментарий