Более низкий параллелизм предпочтителен для массовых вставок документов. Некоторый параллелизм полезен в некоторых обстоятельствах - он зависит от меня, и я пойду в него - но это не крупный или автоматический c выигрыш.
Существует множество параметров, которые можно настроить, когда речь идет о производительности пишет Elasticsearch. Одна очень быстрая победа, которую вы должны проверить: используете ли вы HTTP keep-alive для ваших соединений? Это сэкономит много накладных расходов TCP и TLS при настройке каждого соединения. Именно это изменение может значительно повысить производительность, а также раскрыть некоторые важные архитектурные соображения для вашего конвейера индексирования.
Так что проверьте это и посмотрите, как это происходит. Оттуда мы должны go вниз и продолжить наш путь.
Индекс на диске - Lucene. Lucene - это сегментированный индекс. Часть index является основной причиной, по которой вы в первую очередь используете Elasticsearch: словарь отсортированных терминов можно искать за O (log N). Это супер быстро и масштабируемо. Сегментная часть состоит в том, что вставка в индекс не особенно быстра - в зависимости от вашей реализации, для поддержания сортировки требуется O (log N) или O (N log N).
Так что хитрость Lucene заключается в буферизации эти обновления и добавить новый сегмент; по сути это коллекция мини-индексов. Поиск некоторого относительно небольшого числа сегментов все еще намного быстрее, чем все время, чтобы поддерживать отсортированный индекс при каждом обновлении. Со временем Lucene позаботится о объединении этих сегментов, чтобы удержать их в некотором разумном диапазоне размеров, удалив удаленные и перезаписанные документы в процессе.
В Elasticsearch каждый шард представляет собой отдельный индекс Lucene. Если у вас есть индекс с одним осколком, то иметь несколько параллельных потоков массовых обновлений очень мало пользы. Может быть некоторое преимущество параллелизма на стороне приложения, в зависимости от количества времени, которое требуется вашему конвейеру индексирования для сбора и сборки каждого пакета документов. Но на стороне Elasticsearch это всего лишь один набор буферов, записываемых в один сегмент за другим.
Sharding делает это немного интереснее.
Одна из сильных сторон Elasticsearch - способность раздел данные индекса по нескольким шардам. Это помогает с доступностью, и помогает масштабировать рабочие нагрузки за пределы ресурсов одного сервера.
Увы, это не так просто, как сказать, что параллелизм должен быть равен или пропорционален количеству основных сегментов, которые индекс имеет. Хотя, как грубый heuristi c, это не страшно.
Вы видите, внутри, первый узел Elasticsearch, который обработает запрос, превратит этот групповой запрос в последовательность отдельных действий по обновлению документа. , Каждое обновление документа отправляется соответствующему узлу, на котором размещен фрагмент, к которому принадлежит этот документ. Ответы собираются массовым действием, чтобы он мог отправить сводную информацию о массовых операциях в своем ответе клиенту.
Таким образом, в данный момент, в зависимости от маршрутизации с осколками документов, некоторые осколки могут быть более занятыми, чем другие во время обработки входящего массового запроса. Это может иметь значение ? Моя интуиция говорит не совсем. Это возможно, но это было бы необычно.
В большинстве тестов и анализов, которые я видел, и в моем опыте работы с Lucene в течение ~ десяти лет медленной частью индексации является преобразование значений документов в инвертированный индексный формат. Разбор текста, анализ его в терминах и т. Д. Может быть очень сложным и дорогостоящим. Пока в массовом запросе достаточно документов, которые достаточно хорошо распределены между осколками, параллелизм не так значим, как насыщение работы, выполненной на уровне сегмента и сегмента.
При настройке массовых запросов мой совет вот так.
- Использовать поддержку активности HTTP. Это не обязательно. (Вы используете TLS, верно?)
- Выберите размер пакета, когда каждый запрос занимает скромное количество времени. Где-то около 1 секунды, вероятно, не более 10 секунд.
- Если вы можете придумать, измерьте, сколько времени занимал каждый массовый запрос, и динамически увеличивайте и сокращайте свою партию.
Прочная очередь открывает множество возможностей. Если можно извлекать и собирать документы и вставлять их, скажем, в Kafka, то этот процесс можно запустить параллельно, чтобы насытить базу данных и распараллелить любую денормализацию или подготовку документов. Затем другой процесс извлекает из очереди и отправляет запросы на сервер, и с некоторой легкой координацией вы можете тестировать и настраивать различные параллелизм на разных этапах. Очередь также позволяет вам приостанавливать обновления для различных задач миграции и обслуживания, когда помогает на некоторое время перевести кластер в режим только для чтения.
Я избегал репликации в этом ответе, потому что есть только одна причина, по которой Я бы порекомендовал настроить репликацию. И именно тогда вы массово создаете индекс, который не обслуживает какие-либо производственные потоки c. В этом случае это может помочь сэкономить некоторые ресурсы через ваш серверный парк, чтобы отключить всю репликацию в индекс и включить репликацию после того, как индекс по существу будет загружен данными.
Чтобы закрыть, что, если вы запускаете в любом случае до параллелизма? Каковы риски? Некоторые рабочие нагрузки не контролируют параллелизм, и нет времени или ресурсов, чтобы поставить очередь перед поисковой системой. В этом случае Elasticsearch может избежать довольно значительного количества параллелизма. Он имеет довольно большие пулы потоков для обработки одновременных обновлений документов. Если эти пулы потоков переполнены, он отклонит ответы с сообщением об ошибке HTTP 429 и сообщением об превышении глубины очереди. Они могут повлиять на стабильность кластера в зависимости от доступных ресурсов и количества сегментов в индексе. Но это все довольно заметные проблемы.
Итог: нет, 20 одновременных пакетов с 10 документами в каждом, вероятно, не увеличат производительность по сравнению с 1 пакетом с 200 документами. Если ваши массовые операции выполняются быстро, вы должны увеличивать их размер до тех пор, пока они не будут выполняться в течение одной или двух секунд или проблематичны c. Используйте keep-alive. Если есть другие накладные расходы на стороне приложения, увеличьте ваш параллелизм до 2x или 3x и измерьте эмпирически. Если индексирование является критически важным, используйте быструю и длительную очередь.