Задача 9 из 10
Аналитика в реальном времени
Спроектируйте подсчёт статистики просмотров в реальном времени: сколько уникальных пользователей посмотрели материал и какие материалы в топе за последний час.
Функциональные требования
- Счётчик просмотров по материалу
- Уникальные пользователи за период
- Топ-10 популярного за час и за сутки
- Дашборд, который обновляется почти в реальном времени
Нефункциональные требования
- 100 000 событий в секунду
- Цифры обновляются с задержкой до 30 секунд
- Погрешность в уникальных до 1% допустима
- События приходят с опозданием и дублями
- История хранится год
Нарисуйте архитектуру
Не гонитесь за красотой: на собеседовании от схемы нужно, чтобы по ней было видно путь запроса и где лежат данные. Сначала нарисуйте сами — эталон и разбор ниже.
Блок из палитры — добавить. Тащите мышкой или пальцем. Двойной клик по названию — переименовать. «Связь» — щёлкнуть по одному блоку, потом по другому: получится стрелка.
Схема сохраняется в этом браузере — вкладку можно закрыть и вернуться позже.
1 С чего начать, если ступор
- Посчитайте, сколько памяти нужно на точные уникальные — этот расчёт сам подскажет решение.
- Приблизительные структуры: HyperLogLog для уникальных, Count-Min Sketch для топа.
- Разделите горячий слой (последние минуты) и холодный (история за год).
- События опаздывают: окно агрегации должно уметь принимать прошлое.
- At-least-once из очереди означает, что счётчик может задвоиться — решите, важно ли это здесь.
2 Эталонная схема
Один поток событий и два независимых потребителя: стрим-агрегатор держит последние минуты в Redis, батч складывает часовые агрегаты в историю. Уникальных считаем приблизительно — точность здесь стоит дороже, чем стоит сама цифра.
Это один из рабочих вариантов, а не единственно верный. Если у вас иначе, но вы можете объяснить почему — на собеседовании это ровно то, что нужно.
3 Разбор: что должно прозвучать
Оценка объёма
- Точный подсчёт уникальных требует хранить идентификаторы: миллионы пользователей на каждый материал
- HyperLogLog даёт ~1% погрешности примерно на 12 КБ на счётчик — разница на порядки
- Требование «погрешность до 1% допустима» дано в задаче не случайно: на него надо сослаться
Приблизительные структуры
- HyperLogLog для уникальных, объединяется по периодам без пересчёта
- Count-Min Sketch для топа: память фиксирована, ошибка только в сторону завышения
- Точные счётчики просмотров при этом никто не отменял — они дешёвые
Горячий и холодный слой
- Горячий слой: последние минуты в памяти, быстрый и недолговечный
- Холодный: часовые и суточные агрегаты в аналитическом хранилище
- Дашборд склеивает оба — и это надо явно проговорить, иначе непонятно, откуда цифры
Опоздавшие события
- Событие с мобильного может прийти через час после самого просмотра
- Окно с watermark: до какого момента мы ещё принимаем прошлое, после — отбрасываем или досчитываем
- Время события и время обработки — разные вещи, и путать их нельзя
Дубли
- At-least-once означает, что одно событие обработается дважды
- Дедупликация по идентификатору события в окне или идемпотентные операции
- Для счётчика просмотров дубль на уровне 0.1% часто дешевле, чем дедупликация — но это осознанное решение
Куда копать дальше, если спросят
- Шардирование по ключу материала и горячие материалы, которые не влезают в один шард
- Ретеншен: год истории — это сколько и в каком формате
- Пересчёт задним числом, когда нашли ошибку в агрегации
- Чем отличается lambda-архитектура от kappa и зачем тут два потребителя
Следующая задача: Планировщик отложенных задач
Пять инстансов смотрят в одну таблицу задач. Самая распределённая задача набора: координация, аренда и отсутствие exactly-once.