Как Elasticsearch достигает возврата на уровне миллисекунд для сотен миллионов запросов данных?
Если на собеседовании вы встретите такой вопрос: Как ES повышает эффективность запросов, когда объем данных велик (миллиарды)?
Грубо говоря, это вопрос, чтобы узнать, действительно ли вы использовали ES, из-за чего?На самом деле производительность ES не так хороша, как вы думаете.
Много раз объем данных велик, особенно когда есть сотни миллионов фрагментов данных, вы можете обнаружить, что вы запутались, как запустить поиск 5-10 секунд, и вы будете обмануты.
Когда выполняется первый поиск, это занимает 5~10 секунд, но после этого он будет быстрее, может быть, несколько сотен миллисекунд.
Вы очень запутались.Каждый первый визит пользователя будет медленнее и застревать?Так что, если вы никогда не играли в ES или сами играете в демо-версию, то легко запутаться, задав этот вопрос, который показывает, что вы правы ES правда плохо играет?
Честно говоря, не существует серебряной пули для оптимизации производительности ES. Что вы имеете в виду?Просто не ожидайте, что параметр будет изменен по желанию, и вы можете универсально справиться со всеми сценариями низкой производительности.
Возможно, в некоторых сценариях можно изменить параметры или настроить синтаксис, но это точно не во всех сценариях.
Убийца оптимизации производительности: кэш файловой системы
Данные, которые вы записываете в ES, на самом деле записываются в файл на диске.При запросе операционная система автоматически кэширует данные в файле на диске в кэш файловой системы.
Поисковая система ES в значительной степени зависит от базового кэша файловой системы.Если вы предоставите кэшу файловой системы больше памяти и попытаетесь сделать так, чтобы память вмещала все файлы данных индекса файлов сегментов IDX, то вы в основном будете использовать память при поиске.
Насколько большим может быть разрыв в производительности?Во многих наших предыдущих тестах и нагрузочных тестах, если вы заходите на диск, то обычно это занимает секунды, а производительность поиска точно на втором уровне, 1 секунда, 5 секунд, 10 секунд .
Но если использовать Filesystem Cache и чистую память, то вообще говоря, производительность на порядок выше, чем у диска, в основном в миллисекундах, от нескольких миллисекунд до сотен миллисекунд.
Вот реальный случай: на узле ES компании 3 машины, на каждой машине вроде много памяти по 64G, а всего памяти 64*3=192G.
Каждая машина отдает ES JVM Heap 32G, поэтому остальное для Filesystem Cache составляет всего 32G на машину, а общая память для Filesystem Cache в кластере составляет 32 * 3 = 96G.
В настоящее время файлы данных индекса на всем диске занимают в общей сложности 1 ТБ на трех машинах, а объем данных ES составляет 1 ТБ, поэтому объем данных на каждой машине составляет 300 ГБ. Хорошо ли это работает?
Память кеша файловой системы всего 100G, десятая часть данных может храниться в памяти, а остальные на диске.Затем вы выполняете операцию поиска.Большинство операций выполняется на диске, а производительность конечно плохая.
В конечном счете, вы хотите, чтобы ES работал хорошо.В лучшем случае память вашей машины может вместить как минимум половину вашего общего объема данных.
Согласно нашему собственному практическому опыту в производственной среде, лучше всего хранить небольшой объем данных только в ES, то есть индексы, которые вы хотите искать.Если память, зарезервированная для кэша файловой системы, составляет 100 ГБ, тогда вы будете индексировать данные контролируется в пределах 100G.
В этом случае почти все ваши данные ищутся в памяти, и производительность очень высока, как правило, в течение 1 секунды.
Например, теперь у вас есть ряд данных: id, имя, возраст.... 30 полей. Но если вы ищете сейчас, вам нужно искать только по трем полям: идентификатор, имя и возраст.
Если тупо прописать все поля строки данных в ES, то это приведет к тому, что 90% данных не используются для поиска.
В результате пространство кэша файловой системы на машине ES буквально занято.Чем больше объем данных одного фрагмента данных, тем меньше данных может кэшировать кэш файловой системы.
На самом деле достаточно написать в ES всего несколько полей, которые будут использоваться для поиска, например, написать три поля es id, name и age.
Затем вы можете хранить другие данные поля в MySQL/HBase, обычно мы рекомендуем использовать такую архитектуру ES + HBase.
Особенность HBase в том, что он подходит для онлайн-хранилища массивных данных, то есть может записывать массивные данные в HBase, но не выполнять сложный поиск, а просто выполнять некоторые простые операции, такие как запросы на основе идентификатора или диапазона.
Выполните поиск по имени и возрасту в ES, и результатом может быть 20 идентификаторов документов, а затем в соответствии с идентификатором документа перейдите в HBase, чтобы запросить полные данные, соответствующие каждому идентификатору документа, найти его и затем вернуть на передний план. конец.
Данные, записываемые в ES, предпочтительно должны быть меньше или равны или немного больше объема памяти кэша файловой системы ES.
Затем вы можете потратить 20 мс на получение из ES, а затем запросить в HBase в соответствии с идентификатором, возвращенным ES, и проверить 20 фрагментов данных, что может занять 30 мс.
Может вы раньше так играли, в ES кладется 1Т данных, и каждый запрос будет 5~10с.Теперь производительность может быть очень высокой, и каждый запрос 50мс.
Прогрев данных
Предположим, даже если вы будете следовать приведенному выше плану, объем данных, записываемых каждой машиной в кластере ES, все равно более чем в два раза превышает объем кэша файловой системы.
Например, если вы записываете данные объемом 60 ГБ на машину, в результате кэш файловой системы будет равен 30 ГБ, а на диске все еще останется 30 ГБ данных.
Фактически, предварительный нагрев данных может быть выполнен. Например, возьмем Weibo в качестве примера, вы можете заранее создать систему в фоновом режиме для данных некоторых больших Vs и многих людей, которые обычно ее смотрят.
Время от времени моя собственная фоновая система ищет горячие данные и записывает их в кэш файловой системы.Когда пользователи на самом деле просматривают эти горячие данные позже, они выполняют поиск прямо из памяти, очень быстро.
Или для электронной коммерции вы можете сделать некоторые продукты, которые вы чаще всего просматриваете, например iPhone 8, и заранее создать программу в фоновом режиме, и вы можете активно получать к ней доступ каждую 1 минуту и прошивать ее в кэш файловой системы.
Для данных, которые вы считаете горячими и часто используемыми, лучше всего создать выделенную подсистему прогрева кэша.
Он заключается в том, чтобы время от времени получать доступ к горячим данным заранее, чтобы данные попадали в кэш файловой системы. Таким образом, производительность будет намного лучше, когда другие посетят его в следующий раз.
Горячее и холодное разделение
ES может делать горизонтальное разбиение аналогично MySQL, то есть писать отдельный индекс для большого объема данных, к которым обращаются редко и нечасто, а затем писать отдельный индекс для горячих данных, к которым обращаются часто.
Лучше всего записывать холодные данные в один индекс, а затем записывать горячие данные в другой индекс, чтобы гарантировать, что после разогрева горячих данных, постарайтесь сохранить их в Кэш файловой системы ОС и не допустить, чтобы холодные данные краснеть Потерять.
Видите ли, допустим, у вас есть 6 машин, 2 индекса, один для холодных данных, один для горячих данных и 3 сегмента для каждого индекса. Индекс тепловых данных 3 машин, индекс холодных данных еще 3 машин.
В этом случае вы тратите много времени на доступ к индексу горячих данных, а горячие данные могут составлять 10% от общего объема данных.В это время объем данных очень мал, и почти все хранится в Кэш файловой системы, который может обеспечить скорость доступа к горячим данным, очень высок.
Но для холодных данных он находится в другом индексе, а не на той же машине, что и индекс для горячих данных, и все друг с другом не связаны.
Если кто-то обращается к холодным данным, на диске может быть большой объем данных.В это время производительность низкая, 10% людей обращаются к холодным данным, а 90% людей обращаются к горячим данным, это не не важно.
Дизайн модели документа
Для MySQL у нас часто есть сложные реляционные запросы. Как играть в ES, старайтесь не использовать сложные реляционные запросы в ES, после использования производительность вообще не очень.
Лучше всего сначала завершить ассоциацию в системе Java и записать связанные данные непосредственно в ES. При поиске нет необходимости использовать синтаксис поиска ES для завершения связанных поисков, таких как «Присоединиться».
Дизайн модели документа очень важен.Есть много операций.Не нужно выполнять всевозможные сложные и грязные операции при поиске.
Существует ограниченное количество операций, которые может поддерживать ES. Если есть такая операция, попробуйте выполнить ее, когда модель документа будет спроектирована и написана.
Кроме того, следует по возможности избегать некоторых слишком сложных операций, таких как объединение/вложение/поиск родитель-потомок, а производительность будет очень низкой.
Оптимизация производительности пейджинга
Разбиение по страницам ES сложное, почему? Например, если у вас есть 10 фрагментов данных на странице, и вы хотите запросить 100-ю страницу сейчас, на самом деле будут сохранены первые 1000 фрагментов данных, хранящихся на каждом сегменте. координационный узел.
Если у вас 5 шардов, то есть 5000 фрагментов данных, а затем координирующий узел выполняет некоторое слияние и обработку этих 5000 фрагментов данных, а затем получает последние 10 фрагментов данных на 100-й странице.
Распределенный, вы хотите проверить 10 кусков данных на странице 100. Нельзя сказать, что из 5 шардов каждый шард будет проверять 2 куска данных, и окончательно сливаться в 10 кусков данных на координирующем узле, верно?
Вы должны проверить 1000 фрагментов данных из каждого сегмента, затем отсортировать, отфильтровать и т. д. в соответствии с вашими потребностями и, наконец, снова разбить на страницы, чтобы получить данные на 100-й странице.
Когда вы перелистываете страницы, чем глубже вы перелистываете, тем больше данных возвращает каждый шард и тем дольше обрабатывается координационный узел, что очень раздражает. Поэтому, когда вы используете ES для пейджинга, вы обнаружите, что чем больше вы поворачиваетесь назад, тем медленнее он будет.
Мы также сталкивались с этой проблемой раньше.При использовании ES для подкачки первые несколько страниц занимают всего несколько десятков миллисекунд.Когда мы переходим к 10 или десяткам страниц, в основном требуется 5-10 секунд, чтобы найти страницу данных.
Любое решение?Глубокое пейджинг не разрешено (по умолчанию производительность глубокого пейджинга низкая). Скажите продакт-менеджеру, что ваша система не позволяет вам так глубоко перелистывать страницы. Чем глубже вы перелистываете по умолчанию, тем хуже производительность.
Подобно рекомендуемым продуктам в приложении, которые постоянно пролистываются страница за страницей; аналогично Weibo, где вы проводите вниз, чтобы провести Weibo, и проводите страницу за страницей, вы можете использовать API прокрутки для самостоятельного поиска в Интернете для как это использовать.
Прокрутка создаст снимок всех данных для вас за один раз, а затем каждый раз, когда вы проводите назад и переворачиваете страницу, вы будете перемещаться по курсору scroll_id, чтобы получить следующую страницу и следующую страницу.Производительность будет выше, чем производительность пейджинга, упомянутая выше, очень много, в основном миллисекунды.
Однако единственный момент заключается в том, что это подходит для сцены, похожей на прокрутку страниц Weibo, где вы не можете перейти на любую страницу по своему желанию.
То есть нельзя перейти на страницу 10, потом перейти на страницу 120, потом вернуться на страницу 58, и нельзя просто прыгать.
Поэтому сейчас многие продукты не позволяют вам листать страницы по желанию, есть также приложения и некоторые веб-сайты, вы можете только прокручивать вниз и листать страницу за страницей.
Параметр Scroll должен быть указан при инициализации, сообщая ES, как долго сохранять контекст этого поиска. Вы должны убедиться, что пользователь не будет перелистывать страницы в течение нескольких часов, иначе это может привести к сбою с тайм-аутом.
Вместо использования Scroll API вы также можете сделать это с помощью search_after. Идея search_after состоит в том, чтобы использовать результаты предыдущей страницы, чтобы помочь получить данные следующей страницы.
Очевидно, что этот метод не позволяет вам листать страницы по своему желанию, вы можете только листать страницу за страницей. При инициализации необходимо использовать поле уникального значения в качестве поля Сортировка.