Комментарии 17
Если хотите попасть на следующий стрим по System Design, разбору алгоритмов или просто задать вопросы - подписывайтесь на канал: https://t.me/siliconchannel и на канал c анонсами: https://t.me/silliconanouncment
Если хотите попасть на следующий стрим по System Design, разбору алгоритмов или просто задать вопросы - подписывайтесь на канал: https://t.me/siliconchannel и на канал c анонсами: https://t.me/silliconanouncment
И такую задачу надо решить за 50 минут!
Что не хватает: не нашел обоснование выбора Postgres, Kafka, Redis (например у AWS есть свои альтернативы)
От себя бы добавил в решение: использование самого дешевого хранилища для старых картинок. Например через месяца 2 они протухают и переносятся в медленное хранилище. Это сэкономит кучу денег.
В ленте подписчика храним не пост, а указатель
Когда фан-аут воркер видит, что автор - инфлюенсер, он кладёт в ленту подписчика не post_id, а специальную метку, например influencer:{author_id}.
И в чем выгода? Все равно все 10М подписчиков перебираются на каждый пост инфлюенсера. Разницы с "добавить post_id в ленту подписчика" нет.
Если уж делаем гибрид - то читаем ленту и читаем список подписок. И из списка подписок выбираем инфлюенсеров и их посты. И мержим это все вместе.
Описанная схема полезна разве что для тех, кто очень много контента генерирует - вместо "каждый post_id у каждого подписчика" получим "одна метка у каждого подписчика".
Post Service
...
Постов в ленте на пользователя: 20 (первые 20 записей, которые видны сразу).
Непонятно, как эти 20 записей соотносятся с идеей курсорной пагинации, заложенной в API.
В целом осталось впечатление, что разные части статьи писались в разных диалогах с ИИ (или просто в разное время). В целом получилось неплохо, но согласованности между частями как-то не хватает.
P.S. надеялся увидеть что-нибудь про CQRS, которым подобные вещи и решаются - но не увидел.
P.P.S. тема отказоустойчивости тоже не раскрыта.
Выше @SabMakc отметил непонятность выгоды от записи метки в ленту подписчика — поддержу и добавлю несколько замечаний.
Kafka — это не брокер сообщений, а event streaming platform. Может работать как брокер, но это не совсем по назначению. Для описанных нагрузок (1000 RPS на запись) хватило бы Redis Streams или даже PostgreSQL с outbox-паттерном.
Совершенно непонятно, зачем в рамках этих требований потребовался Neo4j. Операции с подписками — это простые key-value lookups по двум индексам, никаких traversal на глубину 2+. Вот если бы нужно было строить социальный граф с анализом связей или искать кратчайший путь между пользователями — тогда да. А для INSERT/DELETE/SELECT по (follower_id, author_id) это overkill с болезненным горизонтальным шардированием.
Вообще, для таких нагрузок подобное видовое разнообразие технологий не требуется. S3 (или аналог) + PostgreSQL, или S3 + ScyllaDB.
У нас (https://untill.com/untill-air) как раз работает второй вариант в Hetzner: 5 узлов AX41-NVMe, 200 евро в месяц, CQRS, event sourcing. Тестовый стенд стабильно по ночам держит 4000 ops (запись). Три датацентра, падение одного система переживает.

Это базовый минимум что нужно знать, чтобы сегодня попасть в ИТ хоть с опытом хоть без.
Ну в том числе и комменты подтверждают, что с нуля за час такую задачу не решить. А сидеть писать статью в удобном кресле и попивая кофеек - это совсем другое.
Остается только вызубрить решения подобных задач, собственно как и олимпиадных по кодингу.
Если опыт есть - то не так уж и сложно (у автора несколько переусложненное решение получилось).
1000TPS на запись тянет любая СУБД (если просто писать посты), картинки на AWS S3 (причем и чтение, и запись - т.е. через сервис даже трафик не идет), оптимизировать надо только чтение данных, да и то не факт (по постановке задачи, конечно, надо, но в реальной жизни 30к запросов на чтение не означает 30к "тяжелых" запросов на получение ленты).
Ну а оптимизация чтения заметно проще оптимизации смешанной нагрузки. Подходов достаточно: кеширование, кластеризация БД, отдельный сервис для просчета ленты (+дополнительное KV-хранилище, если нужно) и т.д.
У меня есть опыт, если посидеть в спокойной обстановке подумать - то вполне можно ее решить. За день например. Но без подготовки, вот сразу на собес прийти - неа. Будет решено частично или не оптимально. А там ведь толпа других кандидатов, которые ее решали на предыдущем собесе например. Они ее решат «лучше» с точки зрения интервьюера. А это значит отказ.
Так эта задача не на "правильно решить", а для демонстрации своего подхода к решению подобных задачи. Здесь нет единственно верного ответа.
А если интервьювер ожидает строго "правильного" решения, то это все равно угадывать надо "а что там имелось ввиду". Нужны очереди или нет? А может outbox в БД + сервиса хватит? А может KV-хранилище использовать? А может MongoDB? А может просто несколько реплик БД для чтения развернуть? А может железо обновить? А может оптимизировать запросы/структуру БД?
"Правильный" ответ, скорее всего, будет где-то в районе "как у нас эта проблема уже решалась". Т.е. кандидату не угадать в принципе без знания внутренней кухни.
На практике подобные задачи решается в рамках текущего зоопарка технологий, применяемых решений и доступного бюджета. И только если не помогает (а задача достаточно важная) - ищется что-то новое.
"Лучше" я имел ввиду не "правильно", а лучше с точки зрения интервьюера. Тупо неуверенность или больше молчания, стресса и все - ты в пролете. Ну и да в том числе пропустить что-то "важное" именно с точки зрения того, кто спрашивает.
А чем эти факторы отличаются у подобных задач (на дизайн системы) относительно любых других задач/вопросов?
К проведению собеседований есть много вопросов, в том числе и по тому, что кандидат находится в стрессовом состоянии, а интервьюер может быть "себе на уме". А уж когда появляется цепочка собеседований - то становится совсем грустно.
Прохождение собеседований показывает только то, что кандидат умеет проходить собеседования. И очень сложно понять, где кандидат "выезжает" за счет знаний и опыта (как это в идеале и должно быть), где за счет "натасканности", а где вообще за счет ИИ.
Но и альтернатив пока особых не придумали. А цена ошибочного найма очень высока - и речь, прежде всего, о потерянном времени - от нескольких месяцев, а то и от полугода, пока не вскроются проблемы (если вообще вскроются).
Как в таких системах осуществляется модерация постов?
Fan-out-on-read (Pull-модель): При открытии ленты система собирает ID подписок пользователя, запрашивает последние посты у каждого автора, агрегирует и сортирует их. Запись поста дешёвая (O(1)), но чтение очень дорогое (O(количества подписок)). При 150 подписках и 30k RPS система рухнет под нагрузкой запросов к БД.
а почему чтение дорогое? Что значит тут O(количества подписок)?
В реальности - делают именно так. Гибридная модель сильно усложняет систему, не давая плюсов.
Стандартный ответ на дизайн вопрос для успешного прохождения интервью?!!!
По факту - все упирается в производительность Постгреса, и идеи, что "ТЗ точно и неизменно"!, это про лимиты TPS & capacity.

Проектирование сервиса персональной ленты. Как решать System Design?