Требования: отображать число просмотров (и лайков) на странице видео, учитывать каждый просмотр, не считать накрутки, выдерживать вирусные пики. Обычно допустимо: значение отстаёт на секунды, «1,2 млн» вместо точного числа.
Оценка: 50 000 просмотров в секунду в среднем, пики ×5; один вирусный ролик может давать 10% всех просмотров — 25 000 инкрементов в секунду одного ключа.
Почему не прямой UPDATE: каждый инкремент берёт блокировку строки; одна строка выдерживает от сотен до пары тысяч обновлений в секунду, и очередь на блокировку растёт. Плюс WAL и репликация на каждое событие.
Конвейер:
- клиент или сервис раздачи отправляет событие просмотра (видео, пользователь, время, длительность) → балансировщик → приёмник, который сразу кладёт в Kafka (партиции по video_id) и отвечает;
- агрегатор читает партиции, копит счётчики в памяти (
video_id → +N) и раз в 1–5 секунд сбрасывает дельты пачкой: UPDATE ... SET views = views + delta — одна запись вместо тысяч; - смещение Kafka фиксируется после сброса — при падении агрегатора события перечитываются (возможен двойной счёт пачки — либо смириться, либо идемпотентный сброс с номером пачки);
- чтение — из кэша (Redis), обновляемого при сбросе; страница показывает значение с задержкой в секунды.
Горячие ключи: партиция с вирусным видео перегружает одного агрегатора — шардировать ключ (video#0..15) или предагрегировать на приёмниках. В Redis — шардированные счётчики и сумма при чтении.
Уникальные зрители — HyperLogLog на видео и день (12 КБ на ключ), объединение для периодов.
Накрутки: просмотр засчитывается при просмотре дольше N секунд; дедупликация по пользователю/устройству в окне (Redis SET NX с TTL или фильтр Блума); антифрод-анализ потом может «откатить» часть просмотров — поэтому публичное число иногда замирает (как у YouTube на 301).
Аналитика (просмотры по часам, регионам) — те же события в ClickHouse, отдельно от счётчика для страницы.