Реальное RFC

О чем пойдет речь:

Реализация персонализированной ленты постов в социальной сети с поддержкой подписок, лайков, комментариев и уведомлений.

Название сервиса:

social-feed, social-posts, social-notifications

Определите домен:

Social

Язык/framework:

Go/Echo

Терминология:

Пост - публикация пользователя, содержащая текст, изображения или видео.

Лента - персонализированная последовательность постов, отсортированная по времени публикации или алгоритму релевантности.

Подписка - связь между пользователями, где один пользователь (подписчик) получает обновления от другого (автора).

Лайк - положительная реакция пользователя на пост.

Комментарий - текстовая реакция пользователя на пост.

Фолловер - пользователь, который подписан на обновления другого пользователя.

Таймлайн - хронологическая последовательность событий пользователя.

Push-уведомление - мгновенное уведомление о новом контенте или активности.

Постановка задачи:

Контекст:

В настоящее время пользователи социальной сети испытывают сложности с поиском релевантного контента. Отсутствует централизованная система формирования персональной ленты, что приводит к снижению вовлеченности пользователей и времени, проводимого в приложении.

Проблемы:

  1. Пользователи не видят контент от интересующих их авторов
  2. Отсутствует алгоритм ранжирования постов по релевантности
  3. Нет системы уведомлений о новом контенте
  4. Производительность загрузки ленты неудовлетворительна для большого количества пользователей
  5. Отсутствует возможность взаимодействия с постами (лайки, комментарии)

Решение:

Создать систему персонализированной ленты, которая будет:

  • Формировать персональную ленту на основе подписок пользователя
  • Обеспечивать высокую производительность через кеширование и предварительную генерацию
  • Поддерживать интерактивность (лайки, комментарии, репосты)
  • Отправлять уведомления о новом контенте
  • Масштабироваться на миллионы пользователей

План реализации:

  1. Фаза 1: Базовая функциональность
    1. Создание и хранение постов
    2. Система подписок
    3. Базовая лента по хронологии
  2. Фаза 2: Интерактивность
    1. Лайки и комментарии
    2. Счетчики взаимодействий
    3. Уведомления о реакциях
  3. Фаза 3: Оптимизация
    1. Кеширование лент
    2. Предварительная генерация
    3. Алгоритм ранжирования
  4. Фаза 4: Масштабирование
    1. Шардинг базы данных
    2. Горизонтальное масштабирование
    3. Мониторинг и аналитика
Архитектурное описание:
Высокоуровневое


Система состоит из нескольких основных компонентов:

  1. social-posts - сервис для создания и управления постами
  2. social-feed - сервис формирования персональных лент
  3. social-notifications - сервис уведомлений
  4. PostgreSQL - основная база данных для хранения постов, пользователей и связей
  5. Redis - кеш для предварительно сгенерированных лент
  6. Apache Kafka - очередь сообщений для асинхронной обработки событий

Основные потоки данных:

  1. Создание поста: пользователь создает пост → social-posts сохраняет в БД → событие в Kafka → social-feed обновляет ленты подписчиков
  2. Загрузка ленты: пользователь запрашивает ленту → social-feed проверяет кеш → возвращает посты или генерирует новую ленту
  3. Взаимодействие: пользователь ставит лайк → social-posts обновляет счетчики → событие в Kafka → social-notifications отправляет уведомление автору
Детали

1. Структура базы данных

Таблица users:

SQL
CREATE TABLE users (
    id BIGSERIAL PRIMARY KEY,
    username VARCHAR(50) UNIQUE NOT NULL,
    email VARCHAR(100) UNIQUE NOT NULL,
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW()
);

Таблица posts:

SQL
CREATE TABLE posts (
    id BIGSERIAL PRIMARY KEY,
    user_id BIGINT REFERENCES users(id),
    content TEXT NOT NULL,
    image_urls TEXT[],
    likes_count INTEGER DEFAULT 0,
    comments_count INTEGER DEFAULT 0,
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_posts_user_id_created_at ON posts(user_id, created_at DESC);

Таблица follows:

SQL
CREATE TABLE follows (
    id BIGSERIAL PRIMARY KEY,
    follower_id BIGINT REFERENCES users(id),
    following_id BIGINT REFERENCES users(id),
    created_at TIMESTAMP DEFAULT NOW(),
    UNIQUE(follower_id, following_id)
);

CREATE INDEX idx_follows_follower_id ON follows(follower_id);
CREATE INDEX idx_follows_following_id ON follows(following_id);

Таблица likes:

SQL
CREATE TABLE likes (
    id BIGSERIAL PRIMARY KEY,
    user_id BIGINT REFERENCES users(id),
    post_id BIGINT REFERENCES posts(id),
    created_at TIMESTAMP DEFAULT NOW(),
    UNIQUE(user_id, post_id)
);

CREATE INDEX idx_likes_post_id ON likes(post_id);

Таблица comments:

SQL
CREATE TABLE comments (
    id BIGSERIAL PRIMARY KEY,
    user_id BIGINT REFERENCES users(id),
    post_id BIGINT REFERENCES posts(id),
    content TEXT NOT NULL,
    created_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_comments_post_id_created_at ON comments(post_id, created_at DESC);

2. Сервис social-posts

Основные ручки:

  1. POST /v1/posts - создание нового поста
  2. GET /v1/posts/{post_id} - получение поста по ID
  3. PUT /v1/posts/{post_id} - редактирование поста
  4. DELETE /v1/posts/{post_id} - удаление поста
  5. POST /v1/posts/{post_id}/like - лайк поста
  6. DELETE /v1/posts/{post_id}/like - удаление лайка
  7. POST /v1/posts/{post_id}/comments - добавление комментария
  8. GET /v1/posts/{post_id}/comments - получение комментариев

Логика создания поста:

  1. Валидация входных данных
  2. Сохранение поста в БД
  3. Отправка события в Kafka топик post-created
  4. Возврат созданного поста

3. Сервис social-feed

Основные ручки:

  1. GET /v1/feed - получение персональной ленты
  2. POST /v1/follows - подписка на пользователя
  3. DELETE /v1/follows/{user_id} - отписка от пользователя
  4. GET /v1/follows - список подписок

Алгоритм формирования ленты:

  1. Получение списка подписок пользователя
  2. Проверка кеша в Redis (ключ: feed:user:{user_id})
  3. Если кеша нет - генерация ленты:
    1. Получение последних постов от подписок
    2. Сортировка по времени создания
    3. Применение алгоритма ранжирования
  4. Кеширование результата на 10 минут
  5. Возврат ленты пользователю

4. Сервис social-notifications

Основные ручки:

  1. GET /v1/notifications - получение уведомлений пользователя
  2. PUT /v1/notifications/{notification_id}/read - отметка как прочитанное

Типы уведомлений:

  • Новый пост от подписки
  • Лайк поста
  • Комментарий к посту
  • Новый подписчик

5. Обработка событий через Kafka

Топики:

  1. post-created - создание нового поста
  2. post-liked - лайк поста
  3. post-commented - комментарий к посту
  4. user-followed - новая подписка

Пример сообщения в топике post-created:

JSON
{
  "event_type": "post_created",
  "timestamp": "2025-07-07T20:00:00Z",
  "data": {
    "post_id": 12345,
    "user_id": 67890,
    "content": "Пример поста",
    "created_at": "2025-07-07T20:00:00Z"
  }
}

6. Стратегия кеширования

Redis структуры:

  1. feed:user:{user_id} - кеш ленты пользователя (TTL: 10 минут)
  2. post:{post_id} - кеш поста (TTL: 1 час)
  3. user:follows:{user_id} - кеш подписок (TTL: 30 минут)
  4. post:stats:{post_id} - счетчики лайков и комментариев (TTL: 5 минут)

Инвалидация кеша:

  • При создании поста - инвалидация лент подписчиков
  • При изменении подписок - инвалидация кеша подписок
  • При лайке/комментарии - инвалидация статистики поста
Альтернативные варианты реализации
  1. Проблема 1: Стратегия формирования ленты
    1. Решение 1 (Pull-модель) - генерация ленты в момент запроса
      1. Плюсы: актуальные данные, меньше использования памяти
      2. Минусы: высокая нагрузка на БД, медленная загрузка
    2. Решение 2 (Push-модель) - предварительная генерация лент
      1. Плюсы: быстрая загрузка, меньше нагрузки на БД при чтении
      2. Минусы: высокое потребление памяти, сложность поддержки
    3. Вывод: Гибридный подход - Push для активных пользователей, Pull для остальных
  2. Проблема 2: Хранение данных
    1. Решение 1 (PostgreSQL) - реляционная база данных
      1. Плюсы: ACID, сложные запросы, зрелость технологии
      2. Минусы: сложность горизонтального масштабирования
    2. Решение 2 (MongoDB) - документная база данных
      1. Плюсы: гибкость схемы, горизонтальное масштабирование
      2. Минусы: слабая консистентность, сложность транзакций
    3. Вывод: PostgreSQL для основных данных, Redis для кеширования
  3. Проблема 3: Обработка событий
    1. Решение 1 (Синхронная обработка) - немедленная обработка
      1. Плюсы: простота, консистентность
      2. Минусы: высокая латентность, блокирующие операции
    2. Решение 2 (Асинхронная обработка) - очереди сообщений
      1. Плюсы: низкая латентность, отказоустойчивость
      2. Минусы: сложность, eventual consistency
    3. Вывод: Асинхронная обработка через Kafka для масштабируемости
Провалидировать архитектуру с кем-то более опытным
  • Провести архитектурное ревью с техлидом команды
  • Обсудить стратегии масштабирования с платформенной командой
  • Согласовать API контракты с фронтенд командой
  • Проверить совместимость с существующими системами аутентификации
  • Оценить производительность и нагрузочное тестирование