предисловие
Из предыдущих глав мы уже знаем, что Elasticsearch — это распределенная поисковая система анализа в реальном времени, которая позволяет вам исследовать ваши данные с невероятной скоростью и масштабом. Он используется для полнотекстового поиска, структурированного поиска, анализа и комбинации этих трех функций. Elasticsearch может масштабироваться до сотен (или даже тысяч) серверных узлов при обработке петабайт данных.
Несмотря на то, что Elasticsearch является распределенным, он не слишком задействует наших разработчиков, нам нужно только запустить соответствующее количество экземпляров ES (т.е. узлов) и назначить им одинаковыеcluster.name
Пусть они принадлежат одному и тому же кластеру, и нужно только указать индекс при создании индекса.количество осколкова такжеКоличество копийТо есть все остальное отдается ES для реализации самой себя.
Это отличается от распределения базы данных и распределенной реализации solr того же происхождения.Распределенная база данных (подбаза данных и подтаблица) требует от нас указания правил маршрутизации и стратегий синхронизации данных.Распределение solr также зависит от zookeeper, но Elasticsearch их полностью блокирует.
Итак, мы говорим, что Elasticsearch по своей сути распределен, и он был разработан, чтобы скрыть сложность распределения. Elasticsearch почти прозрачен с точки зрения распространения. Мы можем легко запустить программу Elasticsearch с одним узлом на ноутбуке, но если вы хотите запустить программу на кластере из 100 узлов, все будет по-прежнему гладко.
Elasticsearch максимально скрывает сложность распределенных систем. Вот некоторые из действий, которые автоматически выполняются в фоновом режиме:
- Чтобы распределить документы по разным контейнерам или сегментам, документы можно хранить в одном или нескольких узлах.
- Эти сегменты равномерно распределяются по узлам кластера, чтобы сбалансировать нагрузку на процесс индексации и поиска.
- Каждый сегмент реплицируется для поддержки избыточности данных, предотвращая потерю данных из-за сбоя оборудования.
- Направляйте запросы с любого узла в кластере на узел, содержащий соответствующие данные.
- Плавно интегрируйте новые узлы по мере роста кластера, перераспределяя сегменты для восстановления от случайных узлов.
Хотя мы можем хорошо использовать Elasticsearch, не понимая распределенный внутренний механизм реализации Elasticsearch, их понимание поможет нам лучше изучить и понять Elasticsearch с другой точки зрения. Далее мы подробно объясним внутренний механизм реализации Elasticsearch, распределенный в следующих частях.
Принцип кластеризации
Из нашего предыдущего распределенного опыта мы знаем, что улучшить распределенную производительность можно путем приобретения более мощной производительности (Вертикальное расширение,илиВертикальное расширение) или большее количество серверов (Горизонтальное расширение,илиГоризонтальное расширение)реализовать.
Хотя Elasticsearch может извлечь выгоду из более мощных аппаратных устройств, таких как жесткие диски для хранения данных, такие как твердотельные накопители,Вертикальное расширениеИз-за технических и ценовых ограничений аппаратных устройств,Вертикальное расширениеЕсть ограничения. Настоящая масштабируемость исходит изГоризонтальное расширение-- Добавьте дополнительные узлы в кластер и распределите нагрузку и стабильность между этими узлами.
Для большинства баз данных обычно требуются очень большие изменения в приложении, чтобы воспользоваться преимуществами дополнительных ресурсов, которые были масштабированы. Напротив, ElastiSearch по своей сути распределен и знает, как улучшить масштабируемость и доступность, управляя несколькими узлами. Это также означает, что вашему приложению не нужно обращать внимание на эту проблему. Так как же это управляется?
главный узел
Запуск экземпляра ES — это узел, и узел присоединяется к кластеру, устанавливая то же самое в файле конфигурацииcluste.name
и понял. Таким образом, кластер состоит из одного или нескольких одинаковыхcluster.name
Он состоит из сконфигурированных узлов, которые разделяют давление данных и нагрузки. Когда узел добавляется в кластер или удаляется из него, кластер равномерно перераспределяет все данные.
Как режим Master-Plave для других компонентов кластеров (MySQL, Redis), узел будет избран в кластере ES, чтобы статьглавный узел, главный узел отвечает за поддержание глобального состояния кластера и перераспределение сегментов, когда узлы присоединяются к кластеру или покидают его. Для получения подробной информации о выборе главного узла вы можете прочитатьВыбор главного узла.
Все основные API уровня документа (индексирование, удаление, поиск) не взаимодействуют с главным узлом, и главный узел не должен участвовать в изменениях и поиске на уровне документа, поэтому, когда в кластере есть только один главный узел, даже при увеличении трафика это тоже не станет узким местом. Любой узел может стать главным узлом. Если в кластере только один узел, он также является главным узлом.
Поэтому, если мы используем kibana в качестве инструмента манипулирования представлениями, нам нужно толькоkibana.yml
в конфигурационном файлеelasticsearch.url: "http://localhost:9200"
Вы можете установить его в качестве главного узла, и главный узел ES автоматически свяжет и запросит информацию обо всех узлах, осколках и репликах. Таким образом, кибана обычно находится на том же сервере, что и главный узел.
Как пользователь, мы можем отправлять запросы налюбой узел в кластере, включая главный узел. Каждый узел знает, где находится какой-либо документ, и может перенаправить наш запрос непосредственно на узел, в котором хранится нужный нам документ. Независимо от того, на какой узел мы отправляем запрос, он отвечает за сбор данных от каждого узла, содержащего нужные нам документы, и возврат окончательного результата клиенту. Elasticsearch управляет всем этим прозрачно.
механизм обнаружения
Как ES реализует только ту же конфигурациюcluste.name
Как насчет добавления узлов в тот же кластер? ответмеханизм обнаружения(модуль обнаружения).
Механизм обнаружения отвечает за обнаружение узлов в кластере и выбор главного узла. Каждый раз, когда состояние кластера изменяется, другие узлы в кластере узнают об этом состоянии (однако, в зависимости от того, какой механизм обнаружения используется).
Основные механизмы автоматического обнаружения, рекомендуемые в настоящее время ES, следующие:
- Azure classic discoveryплагин, мультикаст
- EC2 discoveryплагин, мультикаст
- Google Compute Engine (GCE) discoveryплагин, мультикаст
- Zen discoveryРеализация по умолчанию, многоадресная/одноадресная рассылка
Здесь представлены определения и различия между одноадресной, многоадресной и широковещательной рассылкой, чтобы мы могли лучше понять механизм обнаружения.
Разница между одноадресной, многоадресной и широковещательной рассылкой:
одноадресная передача: Общение между сетевыми узлами похоже на разговор между людьми. Если один человек разговаривает с другим, это описывается с точки зрения сетевых технологий как «одноадресная передача», когда информация принимается и передается только между двумя узлами. Например, когда вы отправляете и получаете электронную почту и просматриваете веб-страницы, вы должны установить соединение с почтовым сервером и веб-сервером.В это время используется метод одноадресной передачи данных.
многоадресная рассылка: "Многоадресная передача" также может называться "многоадресной", а "многоадресная" может пониматься как обращение одного человека к нескольким людям (но не ко всем присутствующим), что может повысить эффективность вызова. Потому что, если используется метод одноадресной передачи, передача по одному узлу, будет столько процессов передачи, сколько целевых узлов.Этот метод заведомо крайне неэффективен и не желателен.Если вы хотите уведомить определенных людей об одном и том же, но не хотите, чтобы другие знали , очень хлопотно использовать телефон для уведомления по одному.Метод многоадресной рассылки может не только передавать данные всех целевых узлов одновременно, но и достигать цели передачи данных только определенным объектам.Применение многоадресной рассылки в сетевых технологий не так много, онлайн-видеоконференции и онлайн-видео по запросу особенно подходят для многоадресной рассылки.
транслировать: Можно понять, что человек говорит со всеми присутствующими через громкоговоритель трансляции. Преимущество этого в том, что эффективность связи высока, и информация может быть передана всем сразу. данные, не различая цель, но не различая конкретный объект, получающий данные.
Среди перечисленных выше механизмов обнаружения Zen Discovery является встроенным механизмом обнаружения по умолчанию в ES. это обеспечиваетОдноадресная передачаа такжемногоадресная рассылкаи может быть расширен для поддержки облачных сред и других форм обнаружения с помощью подключаемых модулей. Итак, давайте сосредоточимся на том, как Zen Discovery используется в Elasticsearch.
кластеры состоят из одинаковыхcluster.name
состоит из узлов. Когда вы запускаете второй узел на той же машине, если он имеет тот жеcluster.name
конфигурации, он автоматически обнаружит кластер и присоединится к нему. Но при запуске узлов на разных машинах, чтобы присоединиться к одному и тому же кластеру, нужно настроить список хостов unicast для подключения.
Список одноадресных хостов черезdiscovery.zen.ping.unicast.hosts
настроить. Эта конфигурация находится в файле elasticsearch.yml:
discovery.zen.ping.unicast.hosts: ["host1", "host2:port"]
Конкретное значение представляет собой массив хостов или строку, разделенную запятыми. Каждое значение должно приниматьhost:port
илиhost
форма (гдеport
По умолчанию установленоtransport.profiles.default.port
, возвращает, если не установленоtransport.tcp.port
). Обратите внимание, что хост IPv6 должен быть заключен в круглые скобки. Значение по умолчанию для этого параметра127.0.0.1,[:: 1]
.
Elasticsearch официально рекомендует нам использоватьОдноадресная передачазаменятьмногоадресная рассылка. Elasticsearch по умолчанию настроен на использованиеОдноадресная передачаОбнаружение для предотвращения случайного присоединения узлов к кластеру. Только узлы, работающие на одном компьютере, автоматически образуют кластер.
несмотря на то чтомногоадресная рассылкаПо-прежнему доступен в виде плагина, но его никогда не следует использовать в продакшне, иначе вы получите узел, случайно добавленный в продакшн просто потому, что они получили сообщение об ошибке.многоадресная рассылкаСигнал. длямногоадресная рассылкаВ этом нет ничего плохого, многоадресная рассылка может вызвать глупые проблемы и сделать кластер уязвимым (например, сетевой инженер возится с сетью, не сообщая вам об этом, и внезапно все узлы не могут найти друг друга).
Используя одноадресную рассылку, вы можете предоставить Elasticsearch список узлов, к которым он должен попытаться подключиться. Когда узел связывается с членом списка одноадресной рассылки, он получает статус всех узлов во всем кластере, затем связывается с главным узлом и присоединяется к кластеру.
Это означает, что ваш список одноадресной рассылки не обязательно должен содержать все узлы в вашем кластере, ему просто нужно иметь достаточное количество узлов, когда новый узел связывается с одним из них и говорит. Если вы используете главный узел-кандидат в качестве одноадресного списка, вам нужно указать только три узла.
Дополнительные сведения об обнаружении узлов Elasticsearch см.Zen Discovery.
справиться с неудачей
Знакомые с распределенными системами, мы должны знать, что распределенные системы предназначены для повышения доступности и отказоустойчивости. Проблемы в одноточечных системах существуют и в ES.
проблема с одним узлом
Если мы запустим один узел, который не содержит никаких данных и индексов, то наш кластер представляет собой кластер с пустыми узлами контента, сокращеннопустой кластер.
Когда работает только один узел в кластере, это означает, что существует единственная точка отказа — отсутствие избыточности. Самая большая проблема с одним узлом в том, что система не является отказоустойчивой, при выходе из строя сервера, на котором находится один узел, перестает работать весь сервис ES.
Давайте создадим индекс с именем user внутри кластера с пустым узлом. По умолчанию для индекса будет выделено 5 основных сегментов и 1 реплика каждого основного сегмента, но для демонстрационных целей нам будет выделено 3 основных сегмента и 1 реплика (по одной реплике на основной сегмент). Фрагментация):
PUT /user
{
"settings" : {
"number_of_shards" : 3,
"number_of_replicas" : 1
}
}
Теперь наш кластер выглядит так, как показано ниже: все 3 основных сегмента назначены узлу 1.
Проверьте работоспособность кластера на этом этапе.GET /_cluster/health
, мы найдем:
{
"cluster_name": "elasticsearch",
"status": "yellow", # 1
"timed_out": false,
"number_of_nodes": 1,
"number_of_data_nodes": 1,
"active_primary_shards": 3,
"active_shards": 3,
"relocating_shards": 0,
"initializing_shards": 0,
"unassigned_shards": 3, # 2
"delayed_unassigned_shards": 0,
"number_of_pending_tasks": 0,
"number_of_in_flight_fetch": 0,
"task_max_waiting_in_queue_millis": 0,
"active_shards_percent_as_number": 50
}
#1 Значение состояния кластера желтое #2 Количество нераспределенных реплик равно 3
Желтое состояние работоспособности кластера означает, что все основные сегменты работают нормально (кластер может нормально обслуживать все запросы), но не все сегменты реплик находятся в нормальном состоянии. Фактически все 3 шарда реплики не назначены — ни один из них не назначен ни одному узлу. Не имеет смысла хранить и исходные данные, и реплику на одном узле, потому что, как только этот узел будет потерян, мы также потеряем все данные реплики на этом узле.
Основной сегмент и соответствующий сегмент реплики не будут находиться на одном узле. Таким образом, максимальное количество сегментов реплик равно n -1 (где n — количество узлов).
Пока наш кластер в настоящее время функционирует нормально, существует риск потери данных в случае аппаратного сбоя.
Горизонтальное расширение
Поскольку одна точка проблематична, нам нужно всего лишь запустить еще несколько узлов и присоединиться к текущему кластеру, что может повысить доступность и обеспечить аварийное переключение, что являетсяГоризонтальное расширение.
Взяв в качестве примера пользователя выше, после добавления узла новый кластер показан на рисунке выше.
Когда второй узел присоединится к кластеру, этому узлу будут выделены 3 сегмента реплики — по одному сегменту реплики на каждый первичный сегмент. Это означает, что при выходе из строя любого узла в кластере наши данные остаются нетронутыми.
Все вновь проиндексированные документы будут храниться на основном сегменте и параллельно реплицироваться на соответствующие сегменты реплики. Это гарантирует, что мы можем получить документы как из основного, так и из реплики осколков.
cluster-health
Отображаемый статус сейчасgreen
, что означает, что все 6 сегментов (включая 3 основных и 3 сегмента-реплики) работают правильно. Наш кластер теперь не только исправен, но и всегда доступен.
Динамическое расширение
Продукты постоянно обновляются, бизнес растет, и количество пользователей будет продолжать расти. Возможно, емкости индекса, которую мы разработали ранее (3 основных сегмента и 3 сегмента реплики), недостаточно. Данные сегментов и сегментов реплик продолжают накапливаться, что снизит производительность поиска после достижения определенного уровня. Так как же нам масштабировать наше растущее приложение по требованию?
Мы продолжаем расширять емкость двух предыдущих узлов по горизонтали и добавляем еще один узел.В это время состояние кластера показано на следующем рисунке:
Чтобы распределить нагрузку, ES перераспределит осколки. По одному сегменту на узле 1 и узле 2 были перенесены на новый узел узла 3, и теперь каждый узел имеет 2 сегмента вместо предыдущих 3. Это означает, что аппаратные ресурсы (ЦП, ОЗУ, ввод-вывод) каждого узла будут совместно использоваться меньшим количеством сегментов, а производительность каждого сегмента будет повышена.
Шард — это полнофункциональная поисковая система, которая может использовать все ресурсы на узле. Наш индекс с 6 шардами (3 первичных шарда и 3 шарда реплики) можно расширить максимум до 6 узлов, на каждом узле по одному шарду, и каждый шард имеет все ресурсы узла, на котором он находится.
Но что, если мы хотим масштабироваться за пределы 6 узлов?
Количество первичных сегментов определяется при создании индекса. По сути, это число определяет максимальный объем данных, который может хранить этот индекс. (Фактический размер зависит от ваших данных, оборудования и сценария использования.) Однако операции чтения — поиск и возврат данных — могут обрабатываться как первичными осколками, так и осколками-репликами, поэтому при наличии большего количества осколков-реплик вы также будете иметь более высокую пропускную способность.
** Количество первичных сегментов индекса нельзя изменить после создания индекса (значение по умолчанию — 5), но количество реплик на первичный сегмент (значение по умолчанию — 1). Для активной библиотеки индексов это значение можно изменить. в любое время Изменено. **Что касается того, почему количество первичных сегментов индекса нельзя изменить после создания индекса, мы объясним это в главе о принципах хранения документов ниже.
Поскольку количество сегментов реплик можно динамически регулировать в работающем кластере, мы можем масштабировать кластер по мере необходимости. Давайте увеличим количество реплик с 1 по умолчанию до 2:
PUT /user/_settings
{
"number_of_replicas" : 2
}
Как показано ниже, пользовательский индекс теперь имеет 9 сегментов: 3 основных сегмента и 6 сегментов реплик. Это означает, что мы можем масштабировать кластер до 9 узлов, по одному сегменту на каждом узле. По сравнению с исходными 3 узлами производительность поиска кластера может быть улучшена в 3 раза.
Конечно, простое добавление дополнительных сегментов реплики в кластер с тем же количеством узлов не улучшит производительность, поскольку каждый сегмент будет получать меньше ресурсов от узла. Вам нужно добавить больше аппаратных ресурсов, чтобы увеличить пропускную способность.
Но большее количество осколков реплик увеличивает избыточность данных: с приведенной выше конфигурацией узла мы можем потерять 2 узла без потери каких-либо данных.
Сбой узла
Если один из наших узлов выходит из строя, сервер узла не работает или сеть недоступна, при условии, что главный узел 1 выходит из строя, состояние кластера будет следующим:
На этом этапе мы проверяем состояние работоспособности кластера и можем обнаружить, что состояниеred
Указывая на то, что не все первичные осколки работают должным образом.
Узел, который мы закрыли, является главным узлом. И кластер должен иметь главный узел для правильной работы, поэтому первое, что происходит, — это выбор нового главного узла: Node 2.
Мы также потеряли первичные осколки 1 и 2, когда закрыли узел 1, и индексы не работали должным образом без первичных осколков.
К счастью, на других узлах есть полные копии этих двух основных сегментов, поэтому новый основной узел немедленно продвигает соответствующие сегменты реплик этих сегментов на узле 2 и узле 3 до основного сегмента, в это время состояние кластера будетyellow
. Этот процесс продвижения основного сегмента происходит мгновенно, как нажатие переключателя.
Почему наше состояние кластераyellow
вместоgreen
Шерстяная ткань? Хотя у нас есть все три основных сегмента, каждый основной сегмент должен соответствовать 2 сегментам реплики одновременно, а в настоящее время существует только один сегмент реплики. Таким образом, кластер не может бытьgreen
, но нам не о чем беспокоиться: если мы также выключим Node 2, наша программа сможет продолжать работать без потери каких-либо данных, потому что Node 3 хранит копию каждого сегмента.
Если мы перезапустим Node 1, кластер сможет перераспределить отсутствующие осколки реплики, и состояние кластера вернется к исходному нормальному состоянию. Если на узле 1 все еще есть предыдущие сегменты, он попытается использовать их повторно, копируя при этом только измененные файлы данных из основного сегмента.
Обработка конфликтов параллелизма
Самое неприятное в распределенных системах — это конфликты параллелизма, а поскольку ES тоже распределенный, как он справляется с конфликтами параллелизма?
Обычно, когда мы обновляем документ с помощью API индексации, мы можем прочитать исходный документ за один раз, внести свои изменения, а затем переиндексировать весь документ. Выигрывает самый последний запрос на индексацию: тот документ, который был проиндексирован последним, будет уникальным образом сохранен в Elasticsearch. Если другие люди одновременно внесут изменения в этот документ, их изменения будут потеряны.
Много раз это не проблема. Возможно, нашим основным хранилищем данных является реляционная база данных, и мы просто копируем данные в Elasticsearch и делаем их доступными для поиска. Вероятность того, что два человека изменят один и тот же документ одновременно, невелика. Или случайная потеря изменений не является серьезной проблемой для нашего бизнеса.
Но иногда пропустить изменение очень серьезно. Представьте, что мы используем Elasticsearch для хранения инвентаря нашего интернет-магазина, и каждый раз, когда мы продаем товар, мы уменьшаем инвентарь в Elasticsearch.
Однажды руководство решило сделать акцию. Внезапно мы продавали несколько предметов в секунду. Предположим, что есть две веб-программы, работающие параллельно, каждая из которых обрабатывает продажу всех товаров одновременно, что приводит к противоречивым результатам инвентаризации.
Чем чаще вносятся изменения, тем больше промежуток между чтением данных и обновлением данных и тем больше вероятность того, что изменения будут потеряны.
оптимистичный контроль параллелизма — номер версии
В мире баз данных обычно используются два метода, чтобы гарантировать, что изменения не будут потеряны во время одновременных обновлений:
-
пессимистический замок Этот подход, широко используемый реляционными базами данных, предполагает возможность возникновения конфликтующих изменений и, таким образом, блокирует доступ к ресурсам для предотвращения конфликтов. Типичным примером является блокировка строки данных перед ее чтением, гарантирующая, что только поток, установивший блокировку, может изменить строку данных.
-
оптимистическая блокировка Этот подход, используемый в Elasticsearch, предполагает, что коллизии невозможны, и не будет блокировать предпринимаемую операцию. Однако если исходные данные будут изменены между чтением и записью, обновление завершится ошибкой. Затем приложение решает, как разрешить конфликт. Например, обновление можно повторить, использовать новые данные или сообщить о ситуации пользователю.
Делая index , GET и запросы на удаление документов в Elasticsearch, мы указываем, что каждый документ имеет номер _version (версии), который увеличивается при изменении документа.
Elasticsearch использует этот номер _version, чтобы убедиться, что изменения выполняются в правильном порядке. Если старая версия документации появится после новой версии, ее можно будет просто проигнорировать.
Мы можем использовать номер _version, чтобы гарантировать, что конфликтующие изменения в приложении не приведут к потере данных. Мы делаем это, указав номер версии документа, который мы хотим изменить. Если версия не является текущим номером версии, наш запрос не будет выполнен.
Все API для обновления или удаления документа приемлемы.version
параметр, который позволяет вам использовать оптимистичный контроль параллелизма в вашем коде, что является разумным решением.
Оптимистичный контроль параллелизма — внешние системы
Версия — это лишь один из способов ее реализации. Мы также можем использовать контроль версий с внешними системами. Обычная настройка — использовать другие базы данных в качестве основного хранилища данных и использовать Elasticsearch для извлечения данных, что означает, что все изменения в основной базе данных Все они должны быть реплицированы в Elasticsearch, и если за эту синхронизацию данных отвечает несколько процессов, вы можете столкнуться с проблемами параллелизма, подобными описанным ранее.
Если в вашей основной базе данных уже есть номер версии или значение поля, которое можно использовать в качестве номера версии, напримерtimestamp
, то вы можете сделать это в Elasticsearch, добавивversion_type=external
Чтобы повторно использовать эти же номера версий в строках запроса, номера версий должны быть целыми числами больше нуля и меньше9.2E+18
(положительное значение типа long в Java).
Внешние номера версий обрабатываются немного иначе, чем внутренние номера версий, которые мы обсуждали ранее, Elasticsearch не проверяет текущую версию._version
совпадает с номером версии, указанным в запросе, но вместо этого проверяет текущую_version
Это меньше указанного номера версии. Если запрос успешен, внешний номер версии является новым_version
хранить.
Внешние номера версий можно указывать не только при запросах на индексацию и удаление, но и при создании новых документов.
Например, чтобы создать новую запись в блоге с номером внешней версии 5, мы можем сделать это следующим образом:
PUT /website/blog/2?version=5&version_type=external
{
"title": "My first external blog entry",
"text": "Starting to get the hang of this..."
}
В ответе мы видим, что текущий номер версии _version равен 5:
{
"_index": "website",
"_type": "blog",
"_id": "2",
"_version": 5,
"created": true
}
Теперь мы обновляем этот документ, чтобы указать новый номер версии 10:
PUT /website/blog/2?version=10&version_type=external
{
"title": "My first external blog entry",
"text": "This is a piece of cake..."
}
Запрос выполнен успешно, и текущая _version установлена на 10:
{
"_index": "website",
"_type": "blog",
"_id": "2",
"_version": 10,
"created": false
}
Если бы вы повторно выполнили этот запрос, он завершился бы с той же конфликтной ошибкой, которую мы видели ранее, потому что указанный номер внешней версии не больше, чем текущий номер версии Elasticsearch.
Принцип хранения документов
При создании индекса нам нужно указать только количество шардов и реплик, и ES автоматически распределит данные документа по соответствующим шардам и репликам. Итак, как именно файлы распределяются по кластеру и как они получаются из кластера? Хотя Elasticsearch скрывает эти низкоуровневые детали, чтобы мы могли сосредоточиться на развитии бизнеса, мы углубляемся в эти основные технические детали, которые могут помочь вам лучше понять, как данные хранятся в этой распределенной системе.
Как документы направляются в шарды
При индексировании документа документ сохраняется в основном сегменте. Как Elasticsearch узнает, в каком сегменте должен храниться документ? Когда мы создаем документ, как он решает, должен ли документ храниться в сегменте 1 или сегменте 2?
Прежде всего, это определенно не случайно, иначе мы не будем знать, где искать документы в будущем. Фактически этот процесс определяется по следующей формуле:
shard = hash(routing) % number_of_primary_shards
routing
является изменяемым значением, по умолчанию используется значение документа_id
Также установлено на пользовательское значение.routing
пройти черезhash
Функция генерирует число, которое затем делится наnumber_of_primary_shards
(количество первичных осколков), чтобы получить остаток . Распределяется от 0 доnumber_of_primary_shards-1
Остаток между ними — это местоположение осколка, в котором находится искомый документ.
Это объясняет, почему нам нужно определять количество первичных шардов при создании индекса и никогда не менять это число: потому что, если число изменится, все предыдущие значения маршрутов будут недействительными, и документ никогда не будет найден.
Вам может показаться, что, поскольку количество основных сегментов Elasticsearch фиксировано, масштабировать индекс сложно, поэтому важно заранее выделить разумное количество сегментов при создании индекса.
Все API-интерфейсы документов (get, index, delete, bulk, update и mget) принимают файл с именемrouting
Параметр маршрутизации, с помощью которого мы можем настроить сопоставление документов с шардами. Пользовательский параметр маршрутизации можно использовать для обеспечения того, чтобы все связанные документы, например все документы, принадлежащие одному и тому же пользователю, хранились в одном сегменте. Можно получить доступ к большему контенту, связанному с маршрутизациейздесь.
Как взаимодействуют основные сегменты и сегменты реплики
Выше описано, как документ направляется в сегмент, так как же основной сегмент взаимодействует с сегментом реплики?
Предположим, что кластер состоит из трех узлов, он содержит индекс с именем user, есть два основных сегмента, и каждый основной сегмент имеет два сегмента-реплики. Реплики одного и того же шарда не будут размещаться на одной ноде, поэтому наш кластер будет выглядеть так:
Мы можем отправлять запросы на любой узел в кластере. Каждый узел имеет возможность обрабатывать произвольные запросы. Каждый узел знает о местонахождении любого документа в кластере, поэтому он может пересылать запросы непосредственно на желаемый узел. В приведенном ниже примере все запросы отправляются в узел 1, который мы позвонимкоординирующий узел.
При отправке запросов для масштабирования нагрузки лучше опрашивать все узлы в кластере.
Запросы на создание, индексирование и удаление документов — это операции записи, которые должны быть выполнены на основном сегменте, прежде чем их можно будет реплицировать на соответствующие сегменты реплики.
Ниже приведена последовательность шагов, необходимых для успешного создания, индексирования и удаления документов в первичном и вторичном осколках и любых осколках-репликах.
- Клиент отправляет новый, индексирующий или удаляющий запрос на узел 1.
- Узел использует _ID документа, чтобы определить, что документ принадлежит к брату 0. Запрос будет перенаправлен на узел 3, поскольку основной осколок для SARD 0 в настоящее время выделяется на узле 3.
- Узел 3 выполняет запрос на первичном сегменте. В случае успеха он перенаправляет запрос на осколки реплик Node1 и Node2 параллельно. Как только все сегменты реплик сообщат об успехе, узел 3 сообщит об успехе узлу-координатору, который сообщит об успехе клиенту.
Когда клиент получает успешный ответ, изменение документа было выполнено для основного сегмента и всех сегментов реплик, и изменение безопасно.
При обработке запросов на чтение узел-координатор будет балансировать нагрузку, опрашивая все сегменты реплик для каждого запроса.
Когда документы извлекаются, документы, которые были проиндексированы, могут уже существовать в основном сегменте, но еще не были реплицированы на сегменты реплики. В этом случае осколок реплики может сообщить, что документ не существует, но основной осколок может успешно вернуть документ. После того, как запрос на индексирование будет успешно возвращен пользователю, документ будет доступен как в основном сегменте, так и в сегменте реплики.
Личный общедоступный номер: JaJian
Добро пожаловать, нажмите и удерживайте изображение, чтобы подписаться на общедоступный номер: JaJian!
Регулярно предоставлять вам пояснения и анализ связанных технологий первоклассных интернет-компаний, таких как распределенные и микросервисы.