Skip to content

sprosonya/highload

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

65 Commits
 
 

Repository files navigation

Почтовый сервис Mail.ru

Содержание

Тема, целевая аудитория и MVP

Тема

Mail.ru - сервис, предоставляющий пользователям возможность обмена электронными письмами.

MVP

Функционал:

  1. Просмотр писем в папках
  2. Сохранение черновика
  3. Отправка письма (в том числе в ответ и пересылкой)
  4. Удаление писем и черновиков
  5. Создание папки (добавление писем в папку)
  6. Фильтрация писем

Сведения

  1. 50M MAU 1
  2. 16,2 DAU 2
  3. 20 000 000 писем отправляются в день 3
  4. Средняя продолжительность посещения - 7 мин 30 сек 4
  5. Почта mail.ru заблокировала более 6 млрд спам-писем за квартал 5
  6. 37% респондентов проверяют почту несколько раз в сутки, у 22% она всегда открыта в течение дня. Каждый пятый (20%) открывает сервисы раз в день, 11% – раз в неделю. 7% пользуются электронными письмам крайне редко, а 3% уже не помнят, когда проверяли папку «Входящие» последний раз. 6
  7. 50 пб - хранилище mail.ru. Из них 15 пб - письма, 35 пб - вложения (файлы) 7
  8. 12 млрд файлов в хранилищах 7
  9. 1 млн писем в минуту 8
  10. 8 гб - бесплатный размер хранилища писем mail.ru 8
  11. Средний вес письма без вложения 75 кб 9
  12. Максимальный размер вложений 25 мб
  13. 100 млн активных пользователей 10
  14. По данным специалистов Почты Mail.Ru около 50% всех писем в Мобильной Почте Mail.Ru отправляются с вложениями. В каждом пятом письме — два и более прикрепленных файла. Примерно в 80% случаях — это фотографии, 19% — документы, 1% приходится на видеоролики и архивы. 11

Продуктовые показатели

Название Показатель Расчет
MAU 50 млн/месяц из данных
DAU 17 млн/день из данных
Отправка писем 20 млн/день из данных
Получение писем 500 тыс/мин из данных (в данных - пиковая нагрузка с коэффициентом 2)
Письмо без вложения 75 кб из данных
Письмо с вложением 1125 кб Из данных: фотографии: 80% (2000 кб), документы: 19% (500 кб), видеоролики и архивы: 1% (10000 кб)
Средний вес вложения = (0.8×2000) + (0.19×500) + (0.01×10000) = 1795 кб
80% писем с вложениями содержат один файл 1795 кб + 75 кб = 1870 кб
20% писем с вложениями содержат два и более файла (возьмем 2): 2×1795 кб + 75 кб = 3665 кб
Средний вес с вложением = (0.8×1870) + (0.2×3665) = 2229 кб
Средний вес = (0.5×75) + (0.5×2229) = 1152 кб
Хранилище 0,5 гб/пользователь В открытых источниках нет данных о среднем хранилище пользователей и о количестве пользователей. Предположим, что 50 млн MAU - количество хранилищ, а ящики неактивных пользователей удаляются. 50 пб / 100 млн пользователей = 0,52 гб
Проверка почты 3.5 раз/день 37% — проверяют почту несколько раз в сутки (3 раза в день), 22% — почта всегда открыта в течение дня (10 проверок в день), 20% — проверяют почту раз в день, 11% — проверяют почту раз в неделю (0.14 проверки в день), 7% — пользуются почтой крайне редко (предположим, это 0.01 проверки в день), 3% — не помнят, когда проверяли почту (0 проверок в день).
Среднее количество проверок в день = (0.37×3) + (0.22×10) + (0.20×1) + (0.11×0.14) + (0.07×0.01) + (0.03×0) = 3.5261
Пользователи 100 млн В источнике указаны активные пользователи, однако если принять, что неактивные ящики удаляются (полгода бездействия) - можно взять это значение как количество пользователей

Расчет нагрузки

Запрос RPS Расчет RPS Traffic Расчет трафика
Создание и отправка письма 231 Отправка писем / 86400 = 20 млн / 86400 2034 мбит/с Отправка писем * Письмо / 86400 = 20 млн * 1125 кб / 86400
Просмотр страницы писем 689 Проверка почты * DAU / 86400 = 3.5 * 17 млн / 86400 20175 мбит/с Предположим, что при проверке почты открываются входящие на 1 странице (50 писем). Для отображения входящих не требуются вложения, поэтому вес одного письма базовый без вложений
Проверка почты * DAU * 50 * Письмо без вложения / 86400 = 3.5 * 17 млн * 50 * 75 / 86400
Просмотр письма с вложениями 2065 Предположим, что при проверке почты пользователь открывает 3 письма с вложениями, скачивая их.
3 * Проверка почты * DAU / 86400 = 3 * 3.5 * 17 млн / 86400
18157 мбит/с Скачивание 3 писем
3 * Проверка почты * DAU * Письмо с вложением / 86400 = 3 * 3.5 * 17 млн * 1125 кб / 86400
Сохранение черновика 4166 Пусть черновик сохраняется автоматически каждые 10 секунд, а письмо в среднем пишется 3 минуты
Отправка писем * (3 мин / 10 сек) / 86400 = 20 млн * (3 мин / 10 сек) / 86400
123 мбит/с Пусть при написании черновика сохраняется изменение - 75 кб / (3 мин / 10 сек) = 4 кб.
Сохранение вложения из черновика примем уже учтенным при расчете трафика при отправке
Отправка писем * ( 3 мин / 10 сек) * 4 кб / 86400 = 20 млн * ( 3 мин / 10 сек ) * 4 кб / 86400
Модерация спама 8133 Из данных о работе антиспам сервиса почты mail.ru, RPS на модерацию спама = RPS получения письма
Получение писем / 60 = 1 млн / 60
4882 мбит/с Так как антиспам-системы сканируют текстовое содержание, вес письма возьмем за 75 кб (письмо без вложения)
Получение писем * Письмо без вложения / 60 = 500 тыс * 75 кб / 60

Объем хранилищ :

Тип Объем Расчет
Письма 15 пб Из данных
Вложения 35 пб Из данных
Личная информация 96 тб Личная информация - данные (ФИО, пароль, техническая информация, почта) 10 кб + аватарка 1 мб = 1034 кб
Пользователи * 1034 кб = 100 млн * 1034 кб

Глобальная балансировка нагрузки

Распределение трафика по странам 4

Процент Страна
90 % Россия
4 % Казахстан
4 % Белоруссия
1 % Азербайджан
1 % Германия

Исходя из крупных городов этих стран и распределения нагрузки целесообразно ДЦ разместить в Москве

Локальная балансировка нагрузки

Будем использовать L4 и L7 балансировщики:

  1. Балансировка SMTP-трафика (L4):
    NGINX
    Алгоритм: Least Connections
    Задачи: равномерное распределение нагрузки между SMTP-серверами. Используется L4 балансировка, так как анализ содержимого при отправке не происходит
  2. Балансировка IMAP/POP3-трафика (L4):
    NGINX
    Алгоритм: Source IP Hash
    Задачи: сохранение сессий пользователей, так как сессии IMAP/POP3 длительные
  3. Балансировка HTTP/HTTPS-трафика (L7):
    NGINX
    Алгоритм: Round Robin для статики и Least Connections для API
    Задачи: разделение трафика на статический контент и API
  4. Оркестрация сервисами с помощью Kubernetes
  5. Обеспечение отказоустойчивости - keepalived
  6. SSL Termination - сертификаты SSL будет проверять балансировщик, для того, чтобы снизить нагрузку на сервера

Логическая схема данных

Снимок экрана 2025-03-24 в 19 49 13

Таблица User (Пользователи)

Поле Тип данных Размер (байты)
id int 4
email text 255
username text 255
password text 255
avatar_url text 255
created_at timestamp 8
updated_at timestamp 8
Итого 1040

Размер - 100 млн пользователей * 1040 байт = 96 гб
Количество строк - 100 млн

Таблица email (Письма)

Поле Тип данных Размер (байты)
id int 4
title text 255
description text 255
sender_email text 255
recipient_email text 255
message_id int 4
parent_id int 4
date timestamp 8
isRead bool 1
folder_id int 4
created_at timestamp 8
updated_at timestamp 8
isDraft bool 1
Итого 1062

Размер - 100 млн пользователей * 100000 писем у каждого (среднее значение) * 1 кб = 10 пб. Расчет приблизительно верен, так как 15 пб - хранилище писем mail.ru без вложений
Количество строк - 10 000 000 000 000

Таблица folder (Папки)

Поле Тип данных Размер (байты)
id int 4
user_id int 4
order_number int 4
name text 255
created_at timestamp 8
updated_at timestamp 8
is_system bool 1
Итого 292

Размер - 100 млн пользователей * (3 дефолтные папки (входящие, отправленные, спам) + 1 кастомная) * 292 байт = 81 гб
Количество строк - 400 000

Таблица attachment (Вложения)

Поле Тип данных Размер (байты)
id_in_email int 4
email_id int 4
filename text 255
contentType text 255
file_id int 4
Итого 777

Размер - 12 000 000 000 * 777 байт = 3,4 пб
Количество строк - 12 000 000 000

Таблица file (Файлы)

Поле Тип данных Размер (байты)
id int 4
content blob 1050 * 1024
created_at text 255
Итого 514

Размер - 12 000 000 000 файлов (^11) * 1309 кб (средний вес вложения) = 15 пб
Количество строк - 12 000 000 000

Нагрузка на чтение/запись

Таблица Запросы RPS
User (чтение) подгрузка профиля (в локал сторадж), вход (DAU + DAU/2) / 86400 = 295
User (запись) регистрация, обновление профиля MAU / 86400 = 578
Email (чтение) просмотр страницы писем 689
Email (запись) отправка писем, сохранение черновика 231 + 4166 = 4397
Folder (чтение) просмотр страницы писем 689
Attachment (чтение) просмотр письма с вложением 2065
Attachment (запись) отправка писем с вложениями Отправка письма / 2 = 231/2 = 115
File (чтение) просмотр письма с вложением 2065
File (запись) отправка писем с вложениями (Отправка письма / 2) * 0.75 (предположим, что 25% писем с вложениями пересылаются и используется тот же файл) = (231/2)*0.75 = 87

Физическая схема данных

Снимок экрана 2025-03-24 в 21 28 06

Индексы

USER

  1. Уникальный индекс для email для быстрой авторизации

EMAIL

  1. Индекс по date, folder_id, recipient_email дя быстрой загрузки папки с письмами
  2. Индекс для поиска по отправителю sender_email
  3. Индекс для сортировки писем по дате (recipient_email, created_at)
  4. Частичный индекс прочитанные/непрочитанные, черновик

ATTACHMENTS

  1. Индекс по email_id для быстрой загрузки

Выбор баз данных

Таблица БД Комментарий Шардирование Резервирование
Email, Attachments Cassandra Горизонтальное масштабирование (10 трлн записей) и высокая запись (4.3k RPS) Шардирование по хэшу от почты пользователя 3 копии в разных DC
Folder PostgreSQL Таблица редко изменяемая и небольшая, вне схем Без шардирования Синхронная репликация (1 мастер и 2 реплики)
User PostgreSQL Таблица редко изменяемая и небольшая, вне схем Без шардирования Синхронная репликация (1 мастер и 2 реплики)
File Mail Storage S3 Надежное, удобное хранение для файлов с быстрым доступом По хэшу от почты + дате Реплики, снапшоты

Денормализация

  1. Поле unread_count в USER для хранения количества непрочитанных писем (избегаем COUNT при каждом входе)
  2. sender_username, recipient_username, folder_name в EMAIL (избегаем JOIN)
  3. has_attachments в EMAIL (избегаем JOIN)
  4. unread_count в FOLDER (избегаем COUNT)

Клиентские библиотеки / Интеграции

  1. Redis для кэширования
  2. pgx библиотека для PostgreSQL для go
  3. aws/aws-sdk-go/service/s3 для S3 дя go
  4. Cassandra – gocql (Go)

Алгоритмы

Технологии

Технология Область применения Мотивация выбора
Go Бэкенд-сервисы Высокая производительность, многопоточность, микросервисная архитектура
React + TypeScript Фронтенд VDOM + строгая типизация
Cassandra Основное хранилище писем Горизонтальная масштабируемость, высокая доступность, оптимизирована для записи
Mail.ru Cloud Storage Хранение файлов Хранение вложений к письмам. Готовое S3-хранилище без затрат (написано разработчиками mail.ru)
PostgreSQL Хранение пользователей и папок Поддержка транзакций, надежность, хорошая производительность для структурированных данных
Redis Кэширование Для хранения сессий и горячих данных, сверхнизкие задержки
Rabbit MQ Очереди сообщений Обеспечение надежной доставки сообщений при высокой нагрузке
Kubernetes Оркестрация сервисов Автомасштабирование, управление жизненным циклом приложений
NGINX Балансировка нагрузки Высокая производительность, поддержка SSL терминации
Prometheus Мониторинг Сбор и хранение метрик в режиме реального времени
Grafana Визуализация метрик Анализ производительности

Обеспечение надежности

Технология Способ резервирования
PostgreSQL (User, Folder) Master-slave репликация инструментами PostgreSQL с помощью WAL. Синхронная репликация (1 мастер и 2 реплики).
Cassandra (Email, Attachments) Репликация между 3 дата-центрами. Шардирование по хэшу от почты пользователя. Автоматическое восстановление при сбоях.
Mail.ru Cloud Storage Репликация в 3 экземплярах в одном дата-центре, георепликация, snapshots
Redis RDB для создания снимков данных с определённым интервалом. Репликация master-slave для отказоустойчивости.
Nginx При отказе трафик перенаправляется на резервный балансировщик
Rabbit MQ Репликация партиций, хранение логов, снепшоты, резервные брокеры

Схема проекта

Микросервисы:

  • authservice
  • mailservice
  • fileservice
  • userservice
  • deliveryservice
Снимок экрана 2025-05-12 в 14 41 31

Оборудование

Микросервисы deliveryservice
RPS отправка письма 231

mailservice
RPS просмотр страницы писем 689 + отправка писем 231 + сохранение черновика 4166

userservice
RPS 295 (подгрузка профиля) + 578 (регистрация, обновление профиля)

authservice
RPS 295 (вход, регистрация)

fileservice
RPS отправка письма 115 + просмотр письма с вложением 2065

Сервис RPS Пиковый RPS (×2) CPU (ядер) RAM (GB) Обоснование
DeliveryService 231 462 4 8 Лёгкая нагрузка: 1 ядро = ~100 RPS (Go)
MailService 5086 10 172 1020 102 Средняя нагрузка: 1 ядро = ~100 RPS (Go)
UserService 873 1 746 18 18 Средняя нагрузка
AuthService 295 590 6 6 Лёгкая нагрузка
FileService 2180 4 360 440 44 Средняя нагрузка
Nginx L4 7500 15 000 30 30 1 ядро = 500 CPS
Nginx L7 7500 15 000 30 30 1 ядро = 500 RPS
Rabbit MQ 230 460 2 16 Лёгкая нагрузка
Redis 295 590 2 16 Лёгкая нагрузка
Prometheus 7500 15 000 4 32 Лёгкая нагрузка
Хранилища RPS CPU Объем
Cassandra 689 чтение + 231 запись + 4166 запись = 5086. С учетом репликаций и пиковых значений - 20000 2000 ядер 30 пб
S3 mail storage 115 запись + 2065 чтение. С учетом репликаций и пиковых значений - 10000 100 ядер 45 пб
PostgreSQL 295 + 578. С учетом репликаций и пиковых значений - 3500 35 ядер 200 гб

Хостинг-провайдеры

Выбрана модель развертывания с помощью оркестрации в kubernetes. Из-за размера, логичнее развертывать на собственном железе cassandra, а s3 хранение на облачном хранилище экосистемы VK

Название Хостинг Конфигурация Cores Cnt Покупка Аренда
Storage Node own Xeon E5-2690/2x 64GB/24x30TB 2.5 NVMe 1344 42 6.7M$ -
k8s-cluster vkcloud 10x(1CPU/64GB/20HDD) + LB 80 10 - 165,562₽/мес
nginx own AMD EPYC 7313P 32GB 250GB 160 10 26280 $ -

Презентация

https://docs.google.com/presentation/d/1ZHeDCVgibnvxEd7Yey8N097Jg1762YRYZGifeb69R4M/edit?usp=sharing

Список источников

Footnotes

  1. Годовой отчет VK Group

  2. Квартальный отчет VK Group

  3. Регистрация

  4. Анализ трафика 2

  5. Новость

  6. Исследование

  7. Highload++ 2

  8. Highload++ 2

  9. Статистика

  10. Анализ рынка

  11. Новость

About

Highload course

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published