Как обойти гору: эффективные приёмы обработки пользовательских данных

в 11:55, , рубрики: backend, locker, rate-limit
Как обойти гору: эффективные приёмы обработки пользовательских данных - 1

Умный в гору не пойдёт, умный гору обойдёт. А если это гора пользовательских данных? Тогда тоже обойдёт — но не в смысле «вокруг», а буквально заглянет под каждый камень, чтобы ничего не упустить. Разберём в статье, как быстро и эффективно обойти данные, если требуется, к примеру, перенести их в новое хранилище или сделать анализ содержимого.

Меня зовут Андрей Баталов, я старший программист в VK Музыке. Расскажу об эффективных приёмах, которые помогают нам в переобходах аудиообъектов и других данных всех пользователей ВКонтакте.

Итак, представим ситуацию: все новые аудио, которые попадают в систему VK Музыки от пользователей, проходят флоу обработки. В него добавляется этап, который предоставляет новые функции. Они будут доступны только для загружаемых аудио. Чтобы новые функции появились и у ранее загруженных файлов, нужно обойти их и применить к ним добавившийся этап обработки. Иными словами, требуется запустить некий модуль переобхода, который отправит все старые данные на обработку. Отмечу пару её особенностей: она занимает несколько секунд для одной аудюшки и происходит асинхронно.

Вот стартовая схема этого процесса, по ходу статьи будем её совершенствовать:

Как обойти гору: эффективные приёмы обработки пользовательских данных - 2

Во время работы над задачей мы фокусировались на двух моментах:

  • нельзя нарушать обработку новых поступающих файлов;

  • нужно поскорее получить значимый эффект от переобхода.

Пойдём по порядку: вот какие приёмы помогали совершить такой переобход.

Приём 1. Выключатель переобхода

Человеку свойственно ошибаться. Но у ошибок есть приятное качество: большую часть из них можно исправить. Если стало понятно, что в процессе переобхода что‑то упустили, недочёт необходимо устранить. Но это займёт какое‑то время. Чтобы выиграть это время, нужно выключить переобход. Так это выглядит на схеме: 

Как обойти гору: эффективные приёмы обработки пользовательских данных - 3

Выключатель должен срабатывать мгновенно и быть в лёгком доступе у ответственного за переобход. Это сэкономит кучу нервов и времени на исправления.

Приём 2. Очередь-посредник

Если для переобхода используются те же мощности, что и для работы основной функциональности, то может произойти замедление или полная остановка обработки текущего потока задач. Лиха беда начало! Есть ещё один приём, чтобы и с этим справиться.

Можно создать очередь‑посредника для задач из переобхода и настроить её так, чтобы она использовала ресурсы процессинга только в рамках выделенной квоты. Кстати, этот приём помогает сбалансировать нагрузку и в других задачах, связанных с использованием общего ресурса. Взглянем на актуализированную схему:

Как обойти гору: эффективные приёмы обработки пользовательских данных - 4

Приём 3. Rate Limiter

Когда при переобходе обнаруживаются ошибки, в нашем первом приёме предлагается использовать выключатель. Но бывает и противоположная ситуация. Переобход работает даже лучше, чем ожидалось: производится поток запросов, который система не в силах обработать. В таком случае хочется цитировать персонажа легендарного «Брата»: бери ношу по себе, чтоб не падать при ходьбе.

Такой механизм, как Rate Limiter, позволяет ограничить поток событий в единицу времени. Он широко применяется в разработке: например, можно ограничить как доступ к API, так и количество сообщений в личку. Чтобы обуздать поток задач из переобхода, он тоже отлично подойдёт. Вот схема с включением Rate Limiter:

Как обойти гору: эффективные приёмы обработки пользовательских данных - 5

Часто реализация Rate Limiter основывается на механизмах скользящего или фиксированного окна. Рассмотрим простой пример на основе фиксированного окна с использованием хранилища Redis. Обратите внимание, это не production‑ready код, а иллюстрация:

Как обойти гору: эффективные приёмы обработки пользовательских данных - 6

О разных способах реализации Rate Limiter можно почитать в статье «Рейт‑лимиты с помощью Python и Redis». Там описаны интересные подходы.

Приём 4. Исключение дублей

Представьте ситуацию: существует система с множеством аудиообъектов, у каждого своё название, владелец, указатель на аудиофайл. Но, приглядевшись, мы видим, что часть из них созданы на основе одного файла: у них разные названия, разные владельцы, но аудиодорожка одна и та же. В таком случае при переобходе не нужно обрабатывать абсолютно все аудиообъекты в системе. Если важна только аудиодорожка, то другую информацию можно игнорировать. Таким образом, в данной ситуации в качестве ключа переобхода разумно использовать не идентификатор аудиообъекта пользователя, а идентификатор аудиофайла в системе:

Как обойти гору: эффективные приёмы обработки пользовательских данных - 7

Процесс станет значительно быстрее, если не нужно будет делать одну работу несколько раз.

Приём 5. Блокировка 

Обработка происходит не мгновенно. Пока она не закончилась, может нападать куча запросов с одинаковым контентом. Чтобы этого избежать, нужно отклонять новые повторяющиеся запросы, если задача уже в процессе выполнения. Такой приём можно назвать блокировкой, а механизм, который его предоставляет, — Locker.

Так же, как и Rate Limiter, Locker активно используется в серверных приложениях. Действует просто: перед тем как взять задачу в работу, совершается попытка блокировки. Если она успешная, можно продолжить обработку, а если завершилась неудачей — кто‑то уже взял задачу в работу и текущую обработку нужно прекратить. На схеме это выглядит так:

Как обойти гору: эффективные приёмы обработки пользовательских данных - 8

Иллюстративный пример блокировки с помощью Redis:

Как обойти гору: эффективные приёмы обработки пользовательских данных - 9

Приём 6. Ретроспективная подготовка списка горячих данных

Для инициирования переобхода нужна веская причина, так как процесс трудоёмкий, длительный, а если допустить ошибки, может нарушиться стабильность работы системы. Например, если переобход нужен, чтобы перенести какие‑то данные в новое хранилище, которое будет быстрее их отдавать пользователям, то логично начать с тех, которые чаще всего извлекаются, — то есть с горячих данных. Тогда эффект от внедрения нового хранилища наступит быстрее и больше пользователей заметят ускорение. Выделить горячие данные можно, изучив статистику и логи. Так выглядит обновлённая схема:

Как обойти гору: эффективные приёмы обработки пользовательских данных - 10

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

Приём 7. Пороговая фильтрация

Для быстрого эффекта лучше сначала обрабатывать наиболее востребованные данные. Но приём ретроспективной подготовки не распространяется на случаи, происходящие в реальном времени. Чтобы приоритизировать данные здесь и сейчас, нужно настроить пороговую фильтрацию:

Как обойти гору: эффективные приёмы обработки пользовательских данных - 11

Это как Rate Limiter наоборот: фильтр будет пройден только после определённого количества попыток. Например, можно настроить порог так, чтобы в обработку пропускались лишь треки, которые послушали больше 1 000 раз в день. По мере обработки горячих данных этот порог нужно снижать, чтобы переходить к менее популярным.

Заключение

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

Вероятно, многие читатели Хабра сталкивались с задачами переобхода и повторной обработки данных. Поделитесь в комментариях: как вы организовывали этот процесс и какими приёмами пользовались?

Автор: andrey270

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js