Спроектируйте ленту новостей
Вопрос
Спроектируйте ленту новостей соцсети: пользователь подписан на других и видит их посты, новые сверху.
Попробуйте сами
Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
Требования: публикация поста, подписка, лента с пагинацией; порядок по времени (ранжирование вне рамок или упрощённо); лента грузится < 200 мс, допустима задержка появления поста в секунды
Оценка нагрузки: 100 млн DAU, 10 открытий ленты в день ≈ 10 000 RPS чтения, в пике ~30 000; 10 млн постов в сутки ≈ 100 RPS записи; при 200 подписчиках в среднем ≈ 20 000 вставок в ленты в секунду
API: POST /posts; GET /feed?cursor=...&limit=20; POST /users/{id}/follow
Данные: посты в шардированной БД по author_id, граф подписок отдельно, готовые ленты как списки id постов в Redis (последние ~500), медиа в S3
Компоненты: сервис постов, очередь событий публикации, fan-out воркеры, сервис ленты, кеш постов, CDN для медиа
Узкие места: аккаунты-звёзды (гибрид on write + on read), неактивные пользователи (не раскладывать, собирать при входе), пагинация курсором, память Redis, удаление и редактирование постов
Что могут спросить следом
- Как поступить с автором на 30 млн подписчиков?
- Как добавить ранжирование?
- Что если Redis с лентами потерян?
Разбор
Требования: публикация, подписки, лента в обратном хронологическом порядке, загрузка быстрее 200 мс, пост может появиться у подписчиков через несколько секунд. Нагрузка: 100 млн DAU по 10 открытий это около 10 000 RPS чтения, в пике 30 000. Постов 10 млн в сутки, это 100 RPS записи, но при 200 подписчиках в среднем раскладка даёт около 20 000 вставок в ленты в секунду. API: публикация, лента с курсором, подписка. Данные: посты шардирую по author_id, подписки в отдельном хранилище, готовая лента пользователя это список последних 500 id постов в Redis: 100 млн × 500 × 8 байт около 400 ГБ, кластер Redis это выдержит. Компоненты: сервис постов пишет пост и событие в Kafka, fan-out воркеры раскладывают id по лентам подписчиков, сервис ленты берёт id из Redis и подтягивает посты из кеша. Узкое место звёзды: для авторов с миллионами подписчиков не раскладываю, а подмешиваю их свежие посты при чтении. Неактивным ленты не раскладываю, собираю при входе. Если Redis потерян, ленты восстанавливаются сборкой из постов подписок, это медленнее, но работает.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.