Перейти к содержанию

Reddit system design

Функциональные требования

  • Пользователь пишет пост в сабреддит(форум)
    • К посту можно приложить одну картинку
    • Комментарии к посту образуют дерево
    • Пользователи могут писать комментарии к посту и к другим комментариям
    • Пользователи могут ставить лайки постам
  • Пользователь получает нотификацию в приложении
    • Если кто-то лайкнет его пост/комментарий
    • Если кто-то ответит на его пост/комментарий
    • Нотификацию можно отключать в настройках
    • Нотификацию нужно посылать не чаще раза в минуту, чтобы не было спама
  • Пользователь может посмотреть ленту постов из сабреддитов на которые он подписан.
    • Самые популярные по лайкам за день, неделю, месяц
    • Лента должна загружаться моментально

Не функциональные требования

  • 50 млн активных пользователей в день
  • 1 000 000 постов в день
  • 10 000 000 комментариев в день
  • 50 000 000 лайков и дизлайков в день
  • 100 000 000 посещений в день
  • в среднем по 100 постов в день смотрят за каждое посещение, листает ленту не дальше 1000 поста
  • Средний пост занимает 100 символов, но в нем может содержаться ссылка, картинка, видео.

Ключевые моменты

  • Как быстро показать ленту?
    • Заранее строить в кэше ленту для каждого пользователя. Кэш вида (user_id, [post_id])
    • Для постов в малопопулярных сабреддитах использовать модель «Fanout on write». При которой id каждого нового поста копируется прямо в кэш ленты всех подписчиков.
    • Для постов в супер популярных сабреддитах использовать модель «Fanout on read». Добавляем посты из них в ленту пользователя на лету при запросе ленты.
    • Для малоактивных пользователей ленту в кэше не генерируем
    • Кэш в данном случае становится отдельной first-class сущностью. По сути это denormalized index. Имеет смысл его сохранять в хранилище, чтобы не пропал при отказе in-memory кэша.
  • Как быстро доставать посты, которые не попали в кэш?
    • Если используем RDBMS, то создаем большое количество асинхронных реплик. 
Master узел БД отвечает только за запись, все чтения по максимуму стараемся перенести на реплики.
    • Как вариант - использовать распределенное NoSQL решение для хранения постов.
  • Нужно ли использовать шардирование?
    • Reddit хранит в разных БД пользователей, посты, линки. Шардирование не используется. При записи в БД паралельно обновляется запись в кэше.

600

Ссылки