← Назад к вопросам

Как оцениваешь разработку базы данных для VK

1.0 Junior🔥 41 комментариев
#Soft Skills и карьера#Базы данных и SQL

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# Как оцениваешь разработку базы данных для VK

Этот вопрос о системном проектировании БД для огромного масштаба (сотни миллионов пользователей, триллионы записей). Вот мой структурированный подход к оценке.

Шаг 1: Анализ требований

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

Для VK нужно хранить:

  • Профили пользователей
  • Посты в ленте
  • Комментарии
  • Лайки
  • Сообщения
  • Друзья
  • Видео, фото

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

  1. Scale

    • 500M+ активных пользователей
    • Пики нагрузки: 10M queries/sec
    • Размер БД: петабайты данных
  2. Latency

    • P95 < 50ms для read
    • P95 < 200ms для write
    • Real-time notifications
  3. Availability

    • 99.99% uptime
    • Graceful degradation
    • Disaster recovery
  4. Consistency

    • Eventually consistent для большинства
    • Strong consistent для критичных данных

Шаг 2: Архитектурные решения

1. Выбор БД

Для разных типов данных нужны разные БД:

Онлайн данные (user profiles, friends):
→ PostgreSQL или MySQL (ACID, транзакции)
→ Redis для caching и real-time data

Учёт лайков, комментариев (большой объём, горячие данные):
→ HBase или Cassandra (горизонтальная масштабируемость)
→ или ClickHouse для аналитики

Полнотекстовый поиск:
→ Elasticsearch или Sphinx

Мессаджинг (real-time):
→ RabbitMQ, Kafka, Redis streams

2. Sharding стратегия

Делим данные горизонтально, чтобы каждая шарда была управляемого размера:

public class ShardingStrategy {
    
    private static final int SHARD_COUNT = 256;
    
    // Sharding по user_id
    public int getShardId(long userId) {
        return Math.abs((int)(userId % SHARD_COUNT));
    }
    
    // Каждый shard - отдельная БД
    // shard_0 → db_shard_0
    // shard_1 → db_shard_1
    // ...
    // shard_255 → db_shard_255
}

Проблемы sharding:

  • Hot spots (один shard перегружен)
  • Cross-shard queries (запросы к нескольким шардам)
  • Repartitioning при росте (сложно)

3. Репликация и резервирование

┌─────────────────────────────────────┐
│      Primary (writes)               │
│   PostgreSQL shard_0_primary        │
│   - Пишут все изменения             │
└────────┬────────────────────────────┘
         │ WAL replication
         ├─────────────────────┬──────────────────┐
         ↓                     ↓                  ↓
    Replica 1           Replica 2          Replica 3
    (read-only)         (read-only)        (backup)

4. Кэширование многоуровневое

Пользовательский запрос
        ↓
[1] Client-side cache (localStorage, Redis in app)
        ↓ miss
[2] CDN cache (fast, geographic)
        ↓ miss
[3] Redis (in-memory, shared)
        ↓ miss
[4] Database

Шаг 3: Схема данных

Пример для фида новостей

-- Таблица постов (основные данные)
CREATE TABLE posts (
    id BIGINT PRIMARY KEY,
    user_id BIGINT NOT NULL,
    content TEXT,
    created_at TIMESTAMP WITH TIME ZONE,
    updated_at TIMESTAMP WITH TIME ZONE,
    INDEX idx_user_id_created_at (user_id, created_at DESC)
) PARTITION BY RANGE (YEAR(created_at));

-- Таблица лайков (большой объём) - HBase
-- RowKey: user_id:post_id
-- Columns: timestamp, liked

-- Таблица графа друзей
CREATE TABLE friendships (
    user_id BIGINT NOT NULL,
    friend_id BIGINT NOT NULL,
    status VARCHAR(20),  -- pending, accepted
    created_at TIMESTAMP,
    PRIMARY KEY (user_id, friend_id),
    INDEX idx_friend_id (friend_id)
);

-- Таблица уведомлений (time series)
CREATE TABLE notifications (
    id BIGINT,
    user_id BIGINT,
    action_type VARCHAR(50),
    actor_id BIGINT,
    created_at TIMESTAMP
) PARTITION BY RANGE (MONTH(created_at));

Шаг 4: Оптимизация запросов

Проблема: Лента новостей (News Feed)

-- ❌ Медленно - нужно джойнить друзей
SELECT p.* FROM posts p
JOIN friendships f ON p.user_id = f.friend_id
WHERE f.user_id = ?
ORDER BY p.created_at DESC
LIMIT 100;

-- Проблема: друзей может быть 5000+, это дорого

✅ Решение: Pre-computed Feed

// Fanout-on-write
@Service
public class FeedService {
    
    public void onNewPost(Post post) {
        long userId = post.getUserId();
        
        // 1. Получи друзей user'а
        List<Long> followers = getFollowers(userId);
        
        // 2. Добавь пост в их feed cache
        for (Long followerId : followers) {
            String feedKey = "feed:" + followerId;
            redisClient.lpush(feedKey, post.getId());
            redisClient.ltrim(feedKey, 0, 500);  // Keep last 500
        }
    }
    
    public List<Post> getFeed(long userId) {
        // Просто read из cache
        String feedKey = "feed:" + userId;
        List<Long> postIds = redisClient.lrange(feedKey, 0, 99);
        return getPostDetails(postIds);
    }
}

// Проблема: если у user'а 100M followers, это медленно
// Решение: только для активных followers, асинхронно

Альтернатива: Pull-on-Read

// Вычисляем фид на лету (медленнее, но экономнее)
public List<Post> getFeed(long userId) {
    List<Long> friendIds = getFriendIds(userId);
    
    return postRepository.findRecentPostsByUserIds(
        friendIds,
        PageRequest.of(0, 100)
    );
}

Шаг 5: Масштабирование

Vertical Scaling (больше мощи одному серверу)

Подходит до определённого момента:

  • SSD вместо HDD
  • Больше RAM
  • Лучше CPU

Horizontal Scaling (больше серверов)

Необходимо при VK масштабе:

  1. Read replicas

    • Распределяем read запросы
    • Каждый replica может читать свой shard
  2. Write optimization

    • Batch writes
    • Write-through cache
    • Eventually consistent где можно
  3. Geo-distribution

    • Data centres в разных регионах
    • Replication между DC
    • Local reads (низкая latency)

Шаг 6: Мониторинг и обслуживание

Метрики

- Query latency (p50, p95, p99)
- Throughput (queries/sec)
- Replication lag (миллисекунды)
- Shard balance (rows per shard)
- Cache hit ratio

Maintenance операции

# Дефрагментация таблиц
ALTER TABLE posts ENGINE=InnoDB;

# Сжатие логов
PURGE BINARY LOGS BEFORE '2024-01-01';

# Vacuum (PostgreSQL)
VACUUM ANALYZE users;

# Rebalancing шардов (очень сложно)
# Нужно перемещать петабайты данных

Шаг 7: Обработка отказов

Failover strategy

При отказе primary:
1. Detection: мониторинг видит offline
2. Promotion: одна из replicas становится primary
3. Re-routing: приложение переключается
4. Notification: alerting системе

Data loss prevention

  • WAL (Write Ahead Log)
  • Синхронная репликация для критичных данных
  • Асинхронная для некритичных
  • Резервные копии в отдельном DC

Мой примерный план для VK

Year 1-2: Основа

  • PostgreSQL + Sharding (256 shards)
  • Redis для cache и real-time
  • MySQL для analytics

Year 2-3: Масштабирование

  • Добавить Cassandra для high-write data
  • HBase для счётчиков
  • Elasticsearch для поиска

Year 3+: Специализированные системы

  • TiDB или Vitess для distributed SQL
  • Kafka для event streaming
  • ClickHouse для аналитики
  • GraphQL кэширование

Оценка трудоёмкости

Проектирование схемы: 2-4 недели
Реализация sharding: 4-6 недель
Оптимизация запросов: ongoing
Масштабирование: 3-6 месяцев
Операционная готовность: 2-3 месяца

Всего для production: 9-12 месяцев

Ключевые принципы

  1. Думай о scale с начала
  2. Выбери правильное хранилище для каждого типа данных
  3. Кэшируй агрессивно
  4. Реплицируй для надёжности
  5. Мониторь постоянно
  6. Plan for failure
  7. Документируй операции
Как оцениваешь разработку базы данных для VK | PrepBro