об авторе
Лю Ченг, технический эксперт отдела исследований и разработок Ctrip Hotel. Он присоединился к Ctrip в 2014 году и отвечал за разработку нескольких проектов по обработке заказов, а также хорошо разбирался в решении различных проблем с производительностью.
Деловая сцена
С увеличением количества заказов возможности чтения и записи одной базы данных стали увеличиваться. В этом случае шардирование базы данных становится логичным. Для записи после сегментирования просто возьмите модуль в соответствии с размером сегмента. Но как обрабатывать многомерные запросы?
Один из способов — запрашивать по частям, а затем агрегировать в памяти. Однако недостатки очевидны: для тех запросов, которые не возвращают осколки данных, это не только дополнительное потребление производительности на сервере приложений, но и ненужная нагрузка на драгоценные ресурсы базы данных.
Что касается производительности запросов, хотя ее можно улучшить, выполняя параллельные запросы с потоками, многопоточное программирование и агрегирование результатов, возвращаемых базой данных, увеличивают сложность и подверженность ошибкам программирования. Можно представить, как реализован пейджинговый запрос после шардинга, и можно получить некоторый опыт.
Поэтому мы решили создать индекс в реальном времени для сегментированной базы данных и передать запрос в независимый веб-сервис.Чтобы обеспечить производительность, удобство запросов бизнес-приложений улучшено. Тогда возникает вопрос, как построить эффективный сегментированный индекс?
Выбор технологии индексирования
Данные индекса в реальном времени будут включать столбцы, используемые в общих запросах, таких как идентификатор пользователя, номер телефона пользователя, адрес пользователя и т. д., и будут копироваться и распространяться в реальном времени на независимый носитель данных. При запросе индекс будет проверяться в первую очередь.Если индекс уже содержит требуемые столбцы, данные могут быть возвращены напрямую. Если требуются дополнительные данные, можно выполнить вторичный запрос на основе измерения сегмента. Запросы также эффективны, потому что конкретные осколки уже могут быть идентифицированы.
Почему бы не использовать индекс базы данных
Индекс базы данных — это резервная копия данных выбранных столбцов таблицы.
Запросы очень эффективны благодаря строкам, содержащим низкоуровневые адреса дисковых блоков или прямые ссылки на исходные данные. Преимущество заключается в том, что механизм индексации, поставляемый с базой данных, относительно стабилен, надежен и эффективен. Недостатком является то, что с увеличением количества сценариев запросов будет увеличиваться количество индексов.
С развитием бизнеса атрибуты самого заказа достигли тысяч, размерности высокочастотных запросов могут исчисляться десятками, а формы деформации после комбинирования могут достигать сотен видов. Сам индекс не обходится без затрат, каждое добавление, удаление и модификация будут иметь дополнительные операции записи и занимать дополнительное физическое пространство для хранения. Чем больше индексов, тем дороже обслуживание индексов базы данных. Так есть ли другие варианты?
Выбор поисковых систем с открытым исходным кодом
В то время нам в голову пришли поисковые системы с открытым исходным кодом Apache Solr и Elastic Search.
Solr — это поисковая платформа с открытым исходным кодом, построенная на библиотеке классов JAVA Lucene. Предоставляет возможности поиска Lucene в более удобном для пользователя виде. Он существует уже десять лет и является очень зрелым продуктом. Обеспечивает распределенное индексирование, распределение репликации, запрос балансировки нагрузки, автоматический переход на другой ресурс и функции восстановления.
Elastic Search также является распределенной поисковой системой RESTful, построенной на основе Lucene. Предоставляет распределенную систему полнотекстового поиска через интерфейс RESTful и документы Schema Fee JSON. Каждый индекс можно разделить на несколько сегментов, и каждый сегмент может иметь несколько резервных копий.
Оба имеют свои плюсы и минусы. С точки зрения установки и настройки, благодаря более новым продуктам Elastic Search легче и проще в установке и использовании. Что касается поиска, помимо возможностей полнотекстового поиска, которые есть у всех, Elastic Search обеспечивает лучшую производительность для аналитических запросов. Что касается распределения, Elastic Search поддерживает несколько сегментов на сервере и автоматически распределяет сегменты между всеми машинами по мере увеличения количества серверов. С точки зрения сообщества и документации Solr имеет больше накоплений благодаря своему старшинству.
Согласно Google Trends, Elastic Search привлекает больше внимания, чем Solr.
В итоге мы выбрали Elastic Search из-за его легкости, простоты использования и лучшей поддержки дистрибутива.Весь установочный пакет занимает всего несколько десятков мегабайт.
Реализация распространения копий
Чтобы не изобретать велосипед, мы пытаемся найти существующие компоненты. Поскольку база данных представляет собой SQL Server, подходящих компонентов с открытым исходным кодом не найдено. Сам SQL Server имеет функцию мониторинга добавлений, удалений и изменений в режиме реального времени и записывает обновленные данные в отдельную таблицу. Однако он не может автоматически записывать данные в Elastic Search и не предоставляет соответствующих API для связи с указанными приложениями, поэтому мы начали пытаться добиться репликации и распространения на уровне приложений.
Почему дистрибутив не реплицируется с использованием уровня доступа к данным
Первый взгляд на наш уровень доступа к данным может стать прорывом. При каждом добавлении и удалении в приложение базы данных записывайте данные в режиме реального времени в Elastic Search. Однако, приняв во внимание обстоятельства, мы решили искать другие пути:
-
Есть десятки приложений, обращающихся к базе данных, и десятки разработчиков меняют код уровня доступа к данным. Если вы хотите реализовать распространение копий уровня данных, вы должны просмотреть существующий код за более чем десять лет, а затем изменить его. Разработка дорога и подвержена ошибкам;
-
Напишите Elastic Search каждый раз, когда вы добавляете, удаляете или изменяете, что означает, что логика бизнес-процессов тесно связана с репликацией и распространением. Нестабильность Elastic Search или другие сопутствующие факторы напрямую приведут к нестабильности бизнес-процессов. Асинхронно открыть поток для записи Elastic Search? Как быть со сценарием выпуска и перезапуска приложения? Добавить много обработки исключений и логики повторных попыток? А потом ссылались на десятки приложений в виде JAR? Небольшая ошибка, вызывающая нестабильность во всех связанных приложениях?
Сканировать базу данных в режиме реального времени
На первый взгляд это неэффективное решение, но после объединения следующих реальных сценариев это простое, стабильное и эффективное решение:
-
Нулевая связь. Нет необходимости вносить какие-либо изменения в связанные приложения, и это не повлияет на эффективность и стабильность бизнес-процессов.
-
Пишите Elastic Search партиями. Поскольку отсканированные данные находятся в пакетах, их можно записывать в Elastic Search партиями, чтобы предотвратить частое обновление кэша Elastic Search из-за слишком большого количества одиночных запросов.
-
Существует много одновременных операций записи на миллисекундном уровне. При сканировании базы данные не возвращаются, что означает дополнительное потребление производительности базы данных.Параллелизм и объем записи в нашем сценарии очень велики, поэтому такое дополнительное потребление допустимо.
-
Данные не удаляются. Удаленные записи не могут быть проверены путем сканирования базы данных, но записи, относящиеся к заказу, должны быть сохранены, поэтому сценарий удаления данных отсутствует.
Улучшить производительность записи Elastic Search
Из-за репликации и распространения базы данных в реальном времени требования к эффективности и параллельности будут высокими. Вот некоторые из оптимизаций, которые мы использовали для написания Elastic Search:
-
Используйте upsert вместо select + insert/update. Подобно замене в MySQL, он позволяет избежать нескольких запросов и удваивает потребление производительности, вызванное несколькими запросами.
-
Используйте массовый запрос, чтобы объединить несколько запросов в один запрос. Рабочий механизм Elastic Search имеет лучшую производительность для пакетных запросов, например, постоянство транслога по умолчанию находится на уровне запроса, поэтому количество операций записи на жесткий диск будет значительно уменьшено, а производительность записи будет улучшена. Что касается количества запросов в конкретном пакете, то это связано с конфигурацией сервера, структурой индекса и объемом данных. Вы можете использовать динамическую конфигурацию для отладки в рабочей среде.
-
Для индексов с низкими требованиями к реальному времени установите для index.refresh_interval значение 30 секунд (по умолчанию — 1 секунда). Это позволяет Elastic Search создавать новый сегмент каждые 30 секунд, уменьшая нагрузку на последующие сбросы и слияния.
-
Заранее установите схему индекса, чтобы удалить ненужные функции. Например, сопоставление строкового типа по умолчанию создаст как ключевые слова, так и текстовые индексы.Первый подходит для точного сопоставления коротких сообщений, таких как почтовые адреса, имена серверов, метки и т. д., а второй подходит для запроса определенного часть статьи, например содержание электронных писем, описания продуктов и т. д. В зависимости от конкретного сценария запроса вы можете выбрать один из них.
Для полей, которым не важна оценка результатов запроса, вы можете установить norms:false.
Для полей, которые не будут использовать фразовый запрос, установите index_options: freqs.
-
Для индексов, которые допускают потерю данных или сценарии с серверами аварийного восстановления, задайте для index.translog.durability значение async (по умолчанию — запрос). Сохранение записи в lucene на диск является относительно дорогостоящей операцией, поэтому будут транслоги, которые сначала сохраняются на диск, а затем записываются в lucene партиями. Асинхронная запись транслога означает, что нет необходимости записывать на диск каждый запрос, что может повысить производительность записи. Эффект очевиден, когда данные инициализированы, и использование массового запроса для последующей записи в реальном времени может удовлетворить большинство сценариев.
Улучшить производительность чтения Elastic Search
Чтобы повысить производительность запросов, мы внесли следующие оптимизации:
-
При записи укажите самое высокое поле сцены запроса в качестве значения _routing. Поскольку принцип распределенного секционирования Elastic Search заключается в хешировании и модулировании идентификатора документа для определения сегментирования по умолчанию, если для самого высокого поля в сценарии запроса задано значение _routing, это может гарантировать, что при запросе этого поля только один Шардинг возвращает результат.
Напишите:
чек об оплате:
-
Для типов даты уменьшите точность, насколько это может принять бизнес. Он может включать только год, месяц и день, но не часы, минуты и секунды. Когда объем данных велик, эффект от этой оптимизации будет особенно заметен. Потому что чем ниже точность, тем выше частота попаданий в кеш и выше скорость запросов.В то же время повторное использование памяти также повысит производительность сервера Elastic Search, снизит нагрузку на ЦП и уменьшит количество сборщиков мусора. .
Внедрение системного мониторинга
Технический центр разработал систему мониторинга специально для бизнес-подразделений. Он будет периодически вызывать Elastic Search CAT API всех серверов, сохранять данные о производительности на отдельном сервере Elastic Search и предоставлять веб-страницу для мониторинга данных диспетчером приложений.
Реализация аварийного восстановления
Сам Elastic Search является распределенным. При создании индекса мы разделили его на основе общего объема данных за следующие несколько лет, чтобы убедиться, что общий объем данных на сегмент находится в допустимых пределах. Чтобы найти баланс между скоростью записи и аварийным восстановлением, установите узел резервного копирования на 2. Поэтому данные распределяются по разным серверам, и если один сервер в кластере выйдет из строя, другой резервный сервер будет обслуживать напрямую.
В то же время, чтобы предотвратить непредвиденные ситуации, такие как отключение сети или отключение электроэнергии в одном машинном зале, которые могут привести к неправильной работе всего кластера, мы специально развернули набор точно таких же кластеров Elastic Search на другом компьютере. номер в другом регионе. Когда ежедневные данные копируются и распределяются, копия будет одновременно записана в комнату аварийного восстановления в случае чрезвычайной ситуации.
Суммировать
Разработка всего проекта представляет собой постепенный процесс эволюции, и в процессе реализации возникло множество проблем. После запуска проекта процессор и память сервера приложений сильно упали, а скорость запросов осталась практически такой же, как и раньше без шардирования. Здесь мы делимся с вами возникшими проблемами и идеями по их решению.
Ссылаться на
-
официальная документация Elastic Search;
-
https://en.wikipedia.org/wiki/Database_index
-
https://baike.baidu.com/item/%E6%95%B0%E6%8D%AE%E5%BA%93%E7%B4%A2%E5%BC%95
-
https://logz.io/blog/solr-vs-elasticsearch/
【Рекомендуется к прочтению】