С эволюцией современных приложений, обслуживающих растущие потребности в обработке и извлечении данных в реальном времени, растет и потребность в масштабируемости. Одним из таких распределенных поисковых и аналитических движков с открытым исходным кодом является Elasticsearch, который очень эффективен в работе с данными в больших наборах и запросах высокой скорости. Однако процесс эффективного масштабирования Elasticsearch может быть тонким, поскольку необходимо правильно понимать архитектуру, лежащую в его основе, и компромиссы в производительности.
Поскольку распределенная природа Elasticsearch позволяет ему масштабироваться горизонтально, это также вносит больше сложностей в то, как данные распределяются и запросы обрабатываются. Одной из теоретических проблем, связанных с масштабированием Elasticsearch, является его врожденная распределенность. В большинстве практических сценариев чтение на автономном узле всегда будет производительнее, чем чтение в расслоенном кластере. Это связано с тем, что в расслоенном кластере владение данными распределяется по нескольким узлам. Это означает, что каждый запрос может потребовать отправки множества запросов к разным узлам, агрегации результатов на координирующем узле и возврата результата. Этот дополнительный сетевой оверхед легко приведет к увеличению задержки по сравнению с архитектурой с одним узлом, где доступ к данным прямолинеен.
В этом отношении расслоенные кластеры являются фундаментальными для масштабирования Elasticsearch на большие наборы данных, высокий трафик и индексацию почти в реальном времени. Знание тонкого баланса между распределением данных по узлам и поддержанием низкой задержки запроса является ключом к достижению оптимальной производительности. Далее в статье рассматриваются теоретические аспекты масштабируемости Elasticsearch, практические стратегии оптимизации производительности кластера и уроки, извлеченные из опыта внедрения в реальном мире.
На Swoo, нашем приложении для прямых трансляций и игр, Elasticsearch был основой всего поиска, и он отлично справлялся с ростом числа пользователей. В момент, когда количество параллельных пользователей перевалило за 150 000, страница поиска начала иногда выходить из строя, и было ясно, что в кластере Elasticsearch есть какие-то узкие места. Это вскоре стало неприемлемо для живой игровой среды и привело нас к проведению ряда оптимизаций, которые в конечном итоге стабилизировали наши поисковые и домашние страницы.
Понимание архитектуры Elasticsearch для масштабируемости
Elasticsearch изначально поддерживает распределенную архитектуру, что делает систему высокомасштабируемой, но в то же время более сложной по сравнению с традиционными одиночными решениями. Elasticsearch разделяет данные на индексы, причем каждый индекс в свою очередь делится на фрагменты. Фрагмент является основной единицей хранения данных и индексации в Elasticsearch, поскольку система распределяет и параллелизует операции поиска по нескольким узлам кластера.
Типичный кластер содержит ряд узлов данных, на которых хранится часть данных, выполняющих запросы на поиск. По умолчанию Elasticsearch может автоматически распределять данные по узлам, таким образом, что каждый узел выполняет только часть нагрузки запроса. Таким образом, Elasticsearch масштабируется горизонтально: он обрабатывает все больше данных и обслуживает все больше запросов, просто добавляя к нему узлы.
Этот компромисс между масштабируемостью и производительностью запросов, конечно, является одним из самых важных аспектов, которые следует учитывать при проектировании кластеров Elasticsearch, особенно тех приложений, которые требуют высокой пропускной способности при записи в сочетании с низкой задержкой при чтении. Такая задача действительно требует тщательной настройки кластера в сочетании с использованием различных техник оптимизации.
Таким образом, в сущности, наш кластер Elasticsearch имел несколько узлов данных для случая Swoo и три выделенных узла мастера. Каждый узел работал на 8-ядерном процессоре с 16 ГБ оперативной памяти, в основном нацеленный на индексацию в реальном времени и мгновенные поисковые запросы игровых событий. Поскольку мы работаем с высокой конкурентоспособностью, нам необходимо выделить действительно значительную пропускную способность сети, чтобы обеспечить минимальную задержку между узлами.
Планирование стратегии масштабирования
Другими словами, эффективное масштабирование Elasticsearch требует анализа текущих показателей производительности, выявления узких мест и четко поставленных целей в отношении масштабируемости. Например, было бы замечательно мониторить задержку запросов, пропускную способность и общее состояние кластера, чтобы понять ограничения вашего кластера. Вы сможете создать план оптимизации, выявив горячие сегменты, всплески загрузки процессора и проблемы с памятью.
Еще одной важной деятельностью, которая требует внимания при масштабировании Elasticsearch, является планирование мощности. Оценка использования диска, характера трафика и требований к сохранению данных обеспечит правильный размер вашего кластера. В общем, горизонтальное масштабирование (добавление узлов в кластер) обычно является лучшим подходом к увеличению объема данных и трафика. В данном случае, однако, вертикальное масштабирование – улучшение ресурсов отдельных узлов – может быть эффективным.
Наши прогнозы показали рост активных пользователей примерно на 10-15% ежемесячно, при этом каждый пользователь генерирует значительный объем событийных данных в процессе использования игры. Исходя из этих прогнозов, мы ожидали, что наш кластер пройдет здоровый рост параллельных запросов вместе с увеличением объема проиндексированных документов. Поэтому мы проанализировали, будет ли масштабирование горизонтальное путем добавления больше узлов данных или вертикальное путем улучшения наших текущих узлов более подходящим для данного увеличения.
Основные техники масштабирования
Оптимизация Elasticsearch включает в себя ряд стратегий, каждая из которых направлена на различные аспекты системы. Среди наиболее эффективных техник можно выделить оптимизацию ввода данных, управление осколками и оптимизацию использования памяти.
Основные области внимания будут сосредоточены на загрузке данных. Elasticsearch изначально поддерживает массовую индексацию, что означает, что вы можете отправлять действительно большие партии документов в одном запросе. Это снижает накладные расходы и в целом ускоряет процесс индексации. Во-вторых, тонкая настройка интервала обновления может иметь большое значение при быстрой загрузке данных. Вы можете изменить стандартный интервал обновления в одну секунду на более высокое значение, скажем, десять секунд, потому что это снизит стресс от слишком частых обновлений на вашем кластере, и ваши записи будут быстрее.
Другие ключевые причины, которые составляют функцию масштабируемости Elasticsearch, включают управление шардами. Хотя Elasticsearch может масштабироваться горизонтально с помощью шардирования, неправильный размер шардов на самом деле приводит к ухудшению производительности. Слишком большое или слишком маленькое количество шардов приводит к снижению скорости индексации и/или производительности запросов. Успех заключается в балансе для оптимальной производительности в Elasticsearch.
Конечно, управление памятью – это еще один очень важный фактор в масштабировании Elasticsearch. Вы определенно снижаете потребление ресурсов и улучшаете производительность своих запросов, оптимизируя размер кучи JVM, настраивая кэш данных полей и включая кэш запросов. Правильное использование памяти и правильные настройки кэширования могут предотвратить ошибки исчерпания памяти и минимизировать накладные расходы на сборку мусора.
Хорошая часть нагрузки Elasticsearch была вызвана непрерывным внесением данных из реального времени в играх. Мы оптимизировали процессы внесения данных путем пакетной обработки документов через Bulk API. В периоды определенной максимальной нагрузки мы могли дополнительно увеличить размеры пакетов и увеличить период обновления для достижения правильного компромисса между индексацией практически в реальном времени и общей стабильностью кластера.
Решения по масштабированию
Когда масштаб становится огромным, Elasticsearch требует более продвинутых техник для обеспечения производительности. Из них выделяется оптимизация запросов. Вы также можете существенно сократить задержку запроса, написав эффективные запросы, которые минимизируют количество шардов, участвующих в поиске. Например, вы можете выполнять пользовательскую маршрутизацию для направления запросов на конкретные шарды с использованием ключа, такого как идентификатор клиента или категория продукта. Это позволяет Elasticsearch не искать все шарды; следовательно, время и ресурсы, используемые, уменьшаются.
ILM, или управление жизненным циклом индекса, является еще одной отличной функцией для настройки Elasticsearch по мере старения набора данных. Вы сможете перемещать старые данные на более медленное, дешевое хранилище, сохраняя наиболее актуальные на более быстром, более доступном хранилище, масштабируя горячо-тепло-холодную архитектуру. Это поддерживает отличную производительность кластера по мере его роста.
Последние обсуждаемые темы относительно масштабируемости Elasticsearch касаются аппаратных аспектов. По мере роста кластера вам захочется убедиться, что оборудование правильно предоставлено для увеличенной нагрузки. Это означает, что необходимо убедиться, что узлы имеют подходящие процессоры, память и дисковый ввод-вывод для эффективной работы. SSD-накопители или диски NVMe значительно улучшат производительность, особенно для операций индексации и поиска, которые требуют высоких скоростей доступа к данным.
Одним из трудных уроков было то, что назначение только стандартного количества шардов для новых индексов привело бы к проблемам с горячими точками. Мы также нашли оптимальный вариант, при котором ни один шард не был перегружен, так как основная часть обновлений в реальном времени поступала с нашей игровой платформы через индексы с интенсивной записью, перераспределенные по нескольким меньшим шарам, с соответствующей корректировкой реплик.
Теоретические идеи и компромиссы оптимизации
В дополнение к практическим оптимизациям выше, есть несколько интересных теоретических соображений по масштабированию Elasticsearch. Одно из ключевых пониманий связано с компромиссами между масштабируемостью и производительностью запросов в распределенной системе. В частности, отмечается, что хотя шардированные кластеры горизонтально масштабируемы, они действительно увеличивают накладные расходы на запросы, поскольку результаты с нескольких узлов должны быть объединены. Это в контрасте с одним узлом, где данные находятся на локальной машине, и запросы могут выполняться без необходимости “общаться” с другими узлами. Понимание этого компромисса важно, если вы проектируете кластер Elasticsearch, который должен балансировать производительность и масштабируемость.
Еще одним более теоретическим аспектом масштабирования Elasticsearch является концепция локальности данных. Вы можете выполнять запросы только к локальному узлу, на котором размещены соответствующие данные шардов, используя параметр запроса preference=local
. Это минимизирует межузловую связь и снижает задержку запросов. Это также может уменьшить проблемы, связанные с репликацией данных и балансировкой нагрузки. Алгоритм адаптивного выбора реплик Elasticsearch пытается оптимизировать выполнение запросов, выбирая лучший узел реплики в текущих условиях. Однако это не обязательно приводит к наиболее эффективному выполнению запроса.
Первая волна сбоев, с которой мы столкнулись в нашей среде, связана с высоким давлением на кучу JVM. Серверы Elasticsearch изначально работали с минимальными выделениями кучи, что приводило к довольно частым циклам сборки мусора при высокой нагрузке запросов. Мы решили эту проблему, настроив JVM, в частности, согласовав минимальный и максимальный размер кучи на 8 ГБ, что дало Elasticsearch достаточно места для обработки запросов без перегрузки кучи.
Распространенные проблемы и решения
Конечно, масштабирование Elasticsearch не лишено вызовов. Среди распространенных ошибок, которые человек захочет избежать, можно назвать неправильное определение размера шард, отсутствие мониторинга, чрезмерное использование кэширования и неправильное использование управления жизненным циклом индекса. Это сэкономит много времени и ресурсов, если обнаружить их на ранней стадии благодаря проактивной настройке конфигурации.
Одной из основных проблем было неправильное настройка параметров по умолчанию Elasticsearch, как в отношении выделения памяти, так и управления шардами. Параметры по умолчанию нормально работали при умеренной нагрузке, но ломались при пиковой нагрузке. Наше решение было многоуровневым: оно пересмотрело выделение кучи, горячее реплицирование индекса и кэширование на короткий срок для повторяющихся запросов. В целом, это предотвратило повторяющиеся сбои по всему кластеру и очень значительно сократило таймауты.
Практическое руководство по реализации в реальном мире
Масштабирование Elasticsearch потребует планирования, тестирования, развертывания и последующей поддержки. Из этого следует, что хорошие практики, шаблоны конфигурации и тщательное тестирование вашего кластера перед внедрением новых изменений на производство обеспечат беспроблемное масштабирование в стабильный кластер на длительный срок.
- Точная настройка параметров JVM. Мы установили как Xms, так и Xmx на 8 ГБ на каждом сервере Elasticsearch, достигая баланса между доступной системной памятью и требованиями к кучи.
- Оптимизация распределения шардов. Большие индексы были разбиты на меньшие шары, чтобы предотвратить горячие точки и масштабирование реплик для самых активных индексов. Это обеспечивало равномерное распределение запросов по кластеру.
- Включение кэширования с коротким временем жизни. Мы применили кэширование с окном в 1 секунду для часто используемых статических запросов на главной странице и заметили, что это значительно снижает нагрузку на Elasticsearch при повторных запросах, не теряя при этом отзывчивости в реальном времени.
- Мониторинг и итерация. Мы использовали Kibana с некоторыми настраиваемыми панелями управления для наблюдения за состоянием шардов, производительностью JVM и задержками запросов в реальном времени. На основе этих метрик мы постоянно проводили тонкие настройки.
Перспективные планы или расширения технологического стека
Кроме того, для роста мы хотели бы изучить управление жизненным циклом индексов горячего-теплого-холодного уровня, перемещая менее часто запрашиваемые данные на более дешевые узлы, сохраняя при этом высококачественное оборудование для индексации и запросов в реальном времени. Мы изучаем передовые решения для мониторинга и обнаружения аномалий на основе ИИ, чтобы убедиться, что всплески или замедления в необычных запросах хорошо предсказаны и не окажут влияния на пользовательский опыт.
Заключение
Масштабирование Elasticsearch требует понимания архитектуры, тщательного планирования и внедрения лучших практик. Несмотря на то, что Elasticsearch масштабируется горизонтально через шардинг, это создает несколько проблем, которые необходимо контролировать для достижения оптимальной производительности. Высокая масштабируемость и производительность кластера Elasticsearch могут быть обеспечены за счет правильной загрузки данных, управления шардами, использования памяти и оптимизации запросов.
Хотя миграция на Elasticsearch была необходима для Solr в нашем случае, без сомнения, помимо чисто технических вопросов, важным вкладом было понимание теоретических трудностей, которые на самом деле скрыты в распределенных системах. Такой осторожный настрой и креативные решения могут позволить значительно вырасти — многопоставочный единый кластер Elasticsearch — который должен обрабатывать миллионы запросов в день, улучшая производительность запросов при значительно сокращенных временах ответа. Теоретические и практические элементы сочетаются, когда вы масштабируете свою развертку Elasticsearch для обеспечения долгосрочного успеха.
Source:
https://dzone.com/articles/how-to-scale-elasticsearch-to-solve-scalability-issues