System Design

Case Study: Instagram

- **Backend**: Python (Django), некоторые сервисы на Go - **Database**: PostgreSQL (sharded), Cassandra для feed - **Cache**: Memcache, Redis - **Queue**: Celery, Kafka - **ML**: PyTorch для ranking - **CDN**: Facebook's собственный CDN - **Mobile**: React Native (общий код iOS/Android)

Instagram выбирает **eventual consistency** для feed: - Пост может появиться у разных подписчиков с задержкой до минуты - Это приемлемо для social feed - Позволяет горизонтально масштабировать feed generation - DM использует **strong consistency** - сообщения не должны теряться

- **2B+** monthly active users - **500M+** daily Stories users - **100M+** photos uploaded daily - **1B+** likes per day - **~10ms** average feed generation latency

Media Upload Pipeline

Media Upload Pipeline

Зачем это нужно?

Instagram обрабатывает миллиарды фото и видео. Эффективная pipeline обработки медиа критична для UX - пользователи ожидают мгновенной загрузки и отображения.

Что это такое?

Upload pipeline включает: приём файла, валидацию, генерацию множества разрешений, оптимизацию (WebP/AVIF), извлечение метаданных и распространение по CDN. Всё это происходит асинхронно для быстрого ответа пользователю.

Как это работает?

Пример

**Оптимизации для быстрого UX:** ```typescript // 1. Client-side preprocessing // Resize before upload: 12MB → 500KB // Show preview immediately from local file // 2. BlurHash placeholder // 20-30 bytes string → instant gradient preview const blurHash = 'LEHV6nWB2yk8pyo0adR*.7kCMdnj'; // Decode to 4x4 pixel gradient, scale up with CSS blur // 3. Progressive JPEG // Shows low-quality image immediately, refines progressively // 4. Responsive images <img srcset=" ${url}?w=150 150w, ${url}?w=320 320w, ${url}?w=640 640w" sizes="(max-width: 640px) 100vw, 640px" /> ```

Что вы узнали о Media Upload Pipeline?

Feed Generation: Fan-out Strategies

Feed Generation: Fan-out Strategies

Зачем это нужно?

Генерация персонализированного фида для 2B+ пользователей - одна из сложнейших задач. Выбор между fan-out on write и fan-out on read определяет архитектуру всей системы.

Что это такое?

Fan-out on write: при публикации поста он сразу записывается в фид всех подписчиков. Fan-out on read: фид собирается в реальном времени при запросе. Instagram использует гибридный подход.

Как это работает?

Пример

**Расчёт для реального масштаба:** ``` Instagram stats: - 2B+ monthly active users - 500M+ daily active users - Average user follows: 200 accounts - Average user posts: 1 post/week - Celebrity: Cristiano Ronaldo = 500M followers Fan-out on Write для Ronaldo: - 1 пост = 500M записей - 500M * 100 bytes = 50GB data - Latency: минуты Гибридный подход: - Regular users: instant fan-out (< 10K writes) - Celebrities: pull on read (one query per celebrity) - Feed generation: ~50ms (cache + 10-20 celebrity queries) ```

Что вы узнали о Feed Generation: Fan-out Strategies?

Feed Ranking

Feed Ranking

Зачем это нужно?

Хронологический фид не оптимален - пользователи пропускают важный контент. ML-ranking увеличивает engagement и время в приложении. Instagram перешёл на ranked feed в 2016.

Что это такое?

Ranking model предсказывает вероятность взаимодействия (like, comment, share, save) для каждого поста. Модель учитывает сигналы о посте, авторе, отношениях между пользователями и контексте просмотра.

Как это работает?

Пример

**Сигналы relationship strength:** ```typescript // Most predictive signals for close friends: // 1. DM frequency (strongest signal) // 2. Tagged in photos together // 3. Comment on each other's posts // 4. Profile visits // 5. Story views and reactions function computeRelationshipScore(viewer: User, author: User): number { return ( 0.30 * normalize(dmCount(viewer, author)) + 0.25 * normalize(mutualTags(viewer, author)) + 0.20 * normalize(commentInteractions(viewer, author)) + 0.15 * normalize(profileVisits(viewer, author)) + 0.10 * normalize(storyEngagement(viewer, author)) ); } // Result: posts from close friends rank higher // even if they have lower global engagement ```

Что вы узнали о Feed Ranking?

Stories Architecture

Stories Architecture

Зачем это нужно?

Stories - ephemeral контент с 24-часовым TTL. Это требует другой архитектуры: высокая доступность для записи (каждый пост stories), автоматическое удаление, и приоритет на просмотр последних.

Что это такое?

Stories хранятся отдельно от постов с оптимизацией под TTL. Ring buffer на клиенте для навигации, pre-fetching соседних stories, и отдельная система tracking для analytics.

Как это работает?

Пример

**Stories tray ranking:** ```typescript // Factors for tray order: // 1. Unwatched stories first (binary) // 2. Relationship strength (close friends higher) // 3. Recency of latest story // 4. Interaction history (reply frequency) function rankTray(userId: string, tray: StoryTray[]): StoryTray[] { return tray.sort((a, b) => { // Unwatched first if (a.hasUnwatched !== b.hasUnwatched) { return a.hasUnwatched ? -1 : 1; } // Then by score const scoreA = computeTrayScore(userId, a); const scoreB = computeTrayScore(userId, b); return scoreB - scoreA; }); } // Close Friends feature: // Users can mark others as "close friends" // Only close friends see certain stories // Close friends' stories appear first in tray ```

Что вы узнали о Stories Architecture?

Instagram Direct (DM)

Instagram Direct (DM)

Зачем это нужно?

Direct Messages - критичная часть engagement. Требует real-time доставку, надёжность, и масштабирование для миллиардов сообщений. Instagram DM обрабатывает 100M+ сообщений в день.

Что это такое?

DM использует отдельную инфраструктуру от feed: real-time через WebSocket/MQTT, thread-based хранение, и E2E encryption для 'Vanish Mode'. Присутствие (online status) управляется отдельной системой.

Как это работает?

Пример

**Typing indicators:** ```typescript class TypingIndicatorService { // Debounced typing state async setTyping(userId: string, threadId: string): Promise<void> { // Set with 3 second TTL await this.redis.setex( `typing:${threadId}:${userId}`, 3, '1' ); // Broadcast to thread const participants = await this.getParticipants(threadId); for (const participantId of participants) { if (participantId === userId) continue; await this.mqtt.publish(`/user/${participantId}/typing`, { threadId, userId, isTyping: true }); } } // Client calls this on each keystroke (debounced) // TTL handles "stopped typing" automatically } ```

Что вы узнали о Instagram Direct (DM)?

Связанные уроки

  • db-04-cap
Case Study: Instagram

0

1

Войти