Didi Levin с открытым исходным кодом: решение для быстрой загрузки данных

задняя часть

1. Предпосылки

В некоторых бизнес-сценариях Интернета мы часто сталкиваемся с такой ситуацией: при запуске сервиса необходимо загрузить в память большое количество данных, масштаб данных достигает десятков гигабайт, а частота обновления данных низкая (уровень дня, уровень часа, минута). уровень) Статический запрос. Такие как данные бизнес-заказа, правила стратегии автономной добычи, данные дорожной сети карты и т. д. Онлайн-службы обычно загружают как минимум две версии данных из соображений стабильности, и запуск службы обычно занимает несколько минут. Выявленные проблемы включают долгосрочный запуск службы и высокие затраты на оплату труда; очереди запросов не могут быть быстро итерированы, а временные затраты высоки; скорость отката низкая, и большое количество случаев сбоя данных не может быть быстро восстановлено, что приводит к потенциальным угрозам стабильности. .

Молниеносная загрузка и запуск (Левин) — панацея от подобных проблем. Levin — это решение для быстрой загрузки вышеупомянутых низкочастотных обновлений, статического использования и крупномасштабных данных, которое эффективно размещает крупномасштабные статические данные и ускоряет холодный запуск и горячую загрузку сервисов с большим объемом памяти.

2. Принцип

Запуск службы только быстрый, но не прерываемый, но в простом сценарии изменения службы (например, онлайн, откат и восстановление после сбоя), хотя изменения данных не задействованы, перезапуск процесса службы приведет к исчезновению кучи. и данные памяти стека. Так можно ли передавать и повторно использовать данные между процессами? Наиболее эффективным способом передачи данных между процессами является разделяемая память.Общая память может прервать жизненный цикл процесса для достижения повторного использования между процессами, а также имеет эффективность доступа к объектам памяти и достаточное доступное адресное пространство (область сопоставления памяти ниже), рыбу (запуск скорость) и медвежья лапа (эффективность запросов) могут иметь оба.

Рассмотрим сценарий обновления данных, который обычно относится к переключению версий данных.В это время чтение данных с диска неизбежно.Есть ли более эффективный метод преобразования из десятков гигабайт файлов данных в объекты данных в памяти (обычно контейнеры STL)? Учитывая, что если вы напрямую скомпилируете макет памяти объекта данных в автономном режиме и запишете его в двоичный файл, а также выполните однократное выделение общей памяти и чтение операций ввода-вывода при запуске онлайн-сервиса, эффективность загрузки может быть дополнительно улучшена.

После принятия решения об использовании разделяемой памяти и автономной компиляции данных контейнера возникает ключевой вопрос: как поместить контейнер в разделяемую память? Самым большим препятствием является неоднородность памяти указателя и контейнера. Оружие Левина — уменьшение размерности: структура памяти объекта-контейнера одномерна, и в одномерном мире весь объект-контейнер может быть выражен, прочитан и скопирован только с первым адресом плюс длина. Поскольку одна и та же часть разделяемой памяти отображается на разные виртуальные адреса разных процессов, смещения используются вместо указателей в контейнерах для реализации адресно-независимых контейнеров.

Мы также исследовали построенное колесо (межпроцессный контейнер Boost) и обнаружили, что его базовая тестовая производительность не очень хороша: эффективность наиболее часто используемых векторных/хеш-карт запросов примерно на 10–20 % ниже, чем у стандартного контейнера. В конце концов, Левин выбрал собственный контейнер с общей памятью и провел ряд оптимизаций, исходя из использования статических данных, преимуществами которого являются простота и удобство использования, высокая эффективность, хорошая производительность и экономия памяти. И реализуйте незаменимые функции посадки инженерных приложений: такие как проверка памяти общего контейнера, управление версиями.

3. Функции и возможности

▍STL-подобный контейнер общей памяти

Поддерживает контейнеры, размещенные в сегментах общей памяти, включая общие контейнеры vector, set, map, hashset, hashmap и т. д. И поддерживает использование адаптации, комбинирования, специализации и других средств для настройки контейнера общей памяти. Базовый тест показывает, что производительность запросов контейнера Levin выше по сравнению со стандартным контейнером, а эффективность использования памяти имеет очевидные преимущества (подробности см. в тесте производительности).

Levin2.jpg

file

▍Компиляция данных в автономном режиме

Эффективное использование данных — цель онлайн-сервисов, а нормализация данных — обязательное условие для создания сложных систем. Многие системы, ориентированные на данные, делят процесс обработки данных на автономную компиляцию и онлайн-загрузку. Автономная компиляция данных является важной частью эффективного преобразования данных. Использование автономных отдельных узлов для преобразования данных в формат, который можно легко использовать, онлайн-сервисы опускаются. преобразования и сборки для нескольких узлов. Levin поддерживает компиляцию данных в автономном режиме, компилируя необработанные данные в общий двоичный файл макета памяти объекта контейнера, который может быть непосредственно прочитан процессом, обеспечивая более эффективные услуги данных для онлайн-сервисов.

▍Онлайн-загрузка данных

Загрузите файлы данных, скомпилированные на автономном этапе, в указанную область общей памяти и поддержите приложение, проверку, загрузку и выпуск объектов общего контейнера. Онлайн-загрузка данных Levin выполняет однократное выделение и чтение разделяемой памяти, что экономит много системных вызовов выделения памяти brk/mmap в процессе построения, уменьшает количество операций ввода-вывода и еще больше ускоряет загрузку данных онлайн-сервиса. На следующем рисунке показан рекомендуемый процесс использования данных, описанный выше.

Levin3.jpg

file

▍Модуль управления

Когда пользователи используют большое количество общих контейнеров, ситуация с использованием общего контейнера непрозрачна, и легко пропустить выпуск один за другим.Когда служба ненормальна, это приведет к тому, что бесполезные данные будут находиться в пространстве памяти и будут потрачены впустую. ресурсы памяти узла. Levin предоставляет модули управления, которые поддерживают групповое управление общими контейнерами.Общие контейнеры с одинаковым жизненным циклом могут управляться одним и тем же экземпляром модуля управления для унифицированного создания, загрузки и выпуска. Модуль управления также поддерживает функцию глобального поиска общего контейнера. Поддержка функций безопасного выпуска и очистки, чтобы избежать ненормального уничтожения данных контейнера или бесполезной резидентной системы контейнера. Поддерживает настраиваемые методы проверки файлов данных, чтобы сократить время проверки файлов.

▍Переключатель версии

Используйте модуль управления Levin для управления данными контейнера одной и той же версии.При удалении определенной версии соответствующий общий набор контейнеров может быть безопасно и единообразно выпущен, что идеально поддерживает реализацию требований горячего переключения версий пользовательских данных.

4. Внутренняя практика

Практический эффект от внутреннего приложения Levin: время холодного старта и горячей загрузки лендинговых сервисов сокращается с минут до секунд. Использование памяти значительно оптимизировано, статические данные контейнера Levin управляются общей памятью, которая отделена от динамических данных сеанса службы. Наблюдая за сценарием переключения версий данных, количество дисковых операций ввода-вывода значительно сокращается, а джиттер ЦП, вызванный переключением, также значительно снижается. Вышеупомянутые в начале статьи проблемы трудовых ресурсов, затрат времени и скрытых проблем со стабильностью решаются легко. Молниеносная загрузка, вы это заслужили! Начиная

5. Страница проекта

GitHub: github.com/didi/levin Documentation: GitHub.com/brother/Levin/…Добро пожаловать Звезда, приветственный выпуск.