Clickstream — платформа сбора аналитики в Авито.

Clickstream — платформа сбора аналитики в Авито.

Nikita Okunev

Введение

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

Clickstream - это платформа сбора аналитических событий. Она позволяет:

  • Хранить и управлять описанием аналитических событий в одном месте (админ панель)
  • Генерировать созданные события в коде (классы или структуры)
  • Валидировать типы и обязательность полей событий в сгенерированном коде на уровне клиента
  • Защищаться от потерь путем буферизации данных на клиентах (в памяти) и приемщиках (на диске) до отправки в брокер сообщений
  • Роутить событий по топикам для потребителей
  • Конфигурировать метрики в разрезе значений полей
  • Отправлять сообщений на основе событий во вне
  • etc

Собираемая аналитика на текущий момент:

  • 20 миллионов событий в минуту (в пике)
  • Отправка идет из 500+ источников
  • Обрабатываем от 10 до 18 терабайт в день

Концепция

Наша система основана на событиях и предполагает однозначное толкование событий и их полей в системе. Это значит, что одно и то же событие и поле имеет только один бизнес смысл не зависимо от места отправки.

Например: есть поле u, которое выступает идентификатором пользователя. Это поле будет идентификатором пользователя и в событии добавления нового объявления и в событии просмотра телефона. Другого значения у этого поля быть не может.

Такой подход обладает своими минусами:

  • При добавлении нового поля нужно учитывать, что оно уже может быть добавлено в систему. На данный момент у нас 4207 полей, найти среди них дубли крайне сложно, но делать это необходимо.
  • Нужно убеждать команды исправлять ошибки добавления дублирующих полей (или самим их исправлять)
  • Концепцию нужно объяснять при внедрении в новые продукты и при найме новых сотрудников. В целом, порог входа в систему повышается.

Но несмотря на минусы именно этот подход позволяет нам делать инструменты и интерфейсы к ним. Подробнее об этом напишем в следующих статьях.

Как это работает с точки зрения пользователя.

У нас есть три базовые сущности: поле, событие и окружение.

  • Окружение - логическая сущность из которого отправляется событие. Может быть сервисом, фронтендом, микрофронтендом, мобильным приложением или фичей в мобильном приложении. Служит идентификатором места отправки, имеет ответственных людей для обращений с просьбами починить аналитику.
  • Событие - логическое действие. Создание объявления, просмотр телефона или любое другое действие в системе из которой собирается аналитика. События прикрепляются к окружениям. Одно событие может быть прикреплено ко множеству окружений. Поля в событии делятся на 2 типа. Метаполя - всегда есть в любом событии, таких полей всего пять: номер события, номер версии, номер окружения, время отправки и ключ идемпотентности. Поля версий - про них далее.
  • Поле - атрибут события. Имеет тип и обязательность. Поля прикрепляются к событиям, из набора полей создается версия события. Версий событий может быть много, при этом каждая версия - неповторяющийся набор полей. В версии может вообще не быть полей, если важен сам факт наличия события. Также поля могут добавлятся в окружения, при этом они будут добавлены во все события этого окружения. Это сделано для упрощения добавления атрибутов, которые есть только в конкретных окружениях и нужно во всех событиях этого окружения.

Эти сущности создаются аналитиками, после чего разработчики генерируют структуры (или классы) событий к себе в код, заполняют их и отправляют через наши библиотеки. В событиях заполняются только поля версий, метаполя либо заполнены в сгенерированном коде, либо заполняются в библиотеке-отправщике.


Пайплайн доставки событий

Пайплайн Clickstream состоит из следующих узлов (тут разбираем только доставку событий, не конфигурацию в админке):

  • Место отправки - сервис или фронт, который сгенерировал код и начал отправлять события. Обычно имеет внутреннюю очередь в памяти и может пережить кратковременные отказы сети. Долго события не хранит.
  • Clickstream Receiver - сервис приема событий с фронтов и мобильных приложений. Собирает в себе костыли для данных вне сети авито. Например некоторые данные находятся в http-only куках, их нужно проставить в события. Данные долго не хранит, имеет очередь в памяти. Раскатывает как stateless-сервис в k8s.
  • Clickstream Agent - основной приемщик событий. Туда пишут все бековые сервисы + receiver. Раскатывает как DaemonSet в k8s. За счет способа раскатки имеет встроенную базу данных pebble, что позволяет долго время хранить события на дисках куба и переживать долговременный отказ следующего узла пайплайна (1-2 дня точно держит, мы пробовали).
  • Kafka - основное место хранения данных в нашей платформе (двх считается отдельным потребителем кликстрима и не является частью платформы сбора данных) и хранит сырой топик 4 дня. В кафке есть свои пайплайны для обработки и обогащения данных на потоке, но тут этого касаться не будем.
  • Flink - кластер для потоковой аналитики. Очень большая тема, которая будет раскрыта в других статьях.
  • Топики потребителей - оттуда читают данные двх и другие сервисы.

Гарантии

Clickstream как и любая потоковая система имеет гарантии доставки и гарантии сортировки. Но гарантировать стабильную доставку вообще без потерь от мобильного телефона клиента до кафки мы не можем, поэтому даем гарантии на более менее управляемые узлы нашей платформы.

Гарантия доставки - at least once. От агента до конечных топиков мы не теряем события, но зато можем насыпать приличное кол-во дублей. Дублирование связано с нашими сервисами и флинком, который может создать множество дублей при failover. Это приводит к необходимости реализации дедупликации на стороне долговременных хранилищ. Наше двх дедуплицирует по двум полям времени отправки и ключу идемпотентности.

Гарантия сортировки - мы не гарантируем сортировку ни в каком виде. Для построения пользовательских цепочек используются инструменты провязки событий, которые в данной статье затронуты не будут.


Инструменты на основе платформы

Тут будет тизер того, о чем мы подробно расскажем в будущем.

Генерация - подробно опишем генерацию для разных языков и платформ.

  • Бек (Python, PHP, Go)
  • Фронт (BDU, Microfront, Js, Ts)
  • Мобильные приложения (Консистентность в больших монорепах, Yaml - как источник генерации, Flutter, Swift, Kotlin)

Тестирование - расскажем как работать с процессами тестирования, критичными событиями, е2е и юнит тестами.

Мониторинг и качество данных - детально раскроем про базовый мониторинг событий, бизнес мониторинг с разными разрезами на основе флинка, валидацию данных на клиентах и dq тестирования.

Экспорт аналитики во вне - поговорим про то, как сделать эффективный экспорт аналитики во внешние системы, почистить поток от ботов и не вызвать гнев security за передачу персональных данных.

Report Page