Задание — Методические указания
Ведомость — Таблица отчетности
Защита — Презентация
3. Глобальная балансировка нагрузки
4. Локальная балансировка нагрузки
Сервис: Сбербанк Онлайн
Аналоги: Тбанк, ВТБ, Альфа-банк, Райффайзенбанк
Каждый 100-ый взрослый человек на Земле использует Сбербанк Онлайн [2].
Соотношение мужской аудитории к женской - 45% на 55% [2].
Рост аудитории на 2019 г. [2]:
- +61% - среди клиентов старше 45 лет;
- +41% - младше 20 лет;
- +29% - 20 до 45 лет.
За пределами России услугами Сбербанка пользовались около 675 тыс. клиентов. [7]
| Страна | Число клиентов |
|---|---|
| Казахстан | >1 млн. [8] |
| Беларусь | 700 тыс. [8] |
| Украина | 120 тыс. [8] |
| Сербия | 150 тыс. [7] |
| Чехия | 125 тыс. [7] |
| Европейские страны | >700 тыс. [8] |
Доля Сбербанка на рынке в России [1]:
- Активы: 30.1%
- Депозиты физических лиц: 44.6%
- Кредиты физическим лицам: 41.4%
- Корпоративные кредиты: 32.8%
- Зарплатные клиенты: 56.6%
- Остатки на кредитных картах: 45.2%
- Ипотечные кредиты: 55.8%
Вклады чаще всего открывают 20 - 29-летние - 33% [2].
Кредиты больше всех оформляют 30 - 39-летние - 47% [2].
Женщины оформляют почти 60 % всех кредитов и вкладов [2].
Функции, характеризующие сервис:
- Просмотр баланса и истории операций
- Денежные переводы :между своими счетами, другим клиентам Сбера, по номеру телефона
- Оплата услуг: ЖКХ, штрафы, налоги, мобильная связь
- Открытие вкладов и оформление кредитов
- Пуш-уведомления о транзакциях
- Антифрод, проверка безопасности
Ключевой функционал сервиса - проведение платежей и переводов
| Метрика | Значение |
|---|---|
| Активные клиенты, 2025 г. | >110 млн (+0,5 млн с начала года) [6] |
| Monthly Active Users (приложение + веб), 2025 | 84.3 млн [6], [5], [3] |
| Daily Active Users (приложение + веб), 2025 | 42.5 млн [6], [5] |
| Соотношение DAU/MAU, 2025 | >50% [6] |
| Новые сессии в минуту, 2023 г. | 110 тыс./мин. [4] |
| Активные сессии одновременно, 2023 г. | >550 тыс. [4] |
| Длительность активной сессии, 2023 г. | ~5 мин. [4] |
| Частота входов на одного клиента, 2019 | 25 раз в месяц [2] |
В месяц человек пользуется сервисом 25 раз, а средняя продолжительность одной сессии - 5 минут.
Совокупное время пребывания пользователя в приложении в месяц:
25 * 5 мин. = 125 мин.
При условии совершения 1 транзакции в минуту в спокойном режиме, среднее количество транзакций на одного пользователя в месяц составляет:
125 транзакций.
Средний размер одного электронного чека: 60 КБ (максимум 100 КБ).
Тогда объём данных на одного пользователя в месяц:
125 транзакций * 60 КБ = 7500 КБ ≈ 7.32 МБ.
Ежемесячная аудитория приложения - 84.3 млн пользователей.
Значит, ежемесячный объём данных для всей аудитории:
84.3 млн * 7.32 МБ ≈ 588.5 ТБ.
Годовой объём:
12 месяцев * 588.5 ТБ ≈ 7.1 ПБ.
ПАО Сбербанк функционирует с 1991 года, то есть на момент 2025 года - 34 года.
Совокупный объём данных за весь период (при условии стабильной ежемесячной аудитории и активности):
34 года * 7.1 ПБ ≈ 241.4 ПБ.
Суммарное кол. запросов в секунду (RPS) составляет >120 тыс./сек. [4].
Предположим, что за 5-минутную сессию типичный пользователь совершает:
| Действие | Раз за сессию | Раз в сутки * |
|---|---|---|
| Авторизация | 1/30 ≈ 0.033 [9] | 1,4 тыс |
| Получение баланса | 2-3 | 106.25 млн |
| Получение чека | 0.3–0.6 | 19.13 млн |
| История платежей | 2/7 ≈ 0.3 | 12.7 млн |
| Открытие вкладов | - | 1.5 тыс [15] |
| Открытие кредит | - | 50 тыс [16] |
| Открытие ипотек | - | 3.1 тыс [17] |
| Перевод по СБП | - | 50.5 млн [13] |
| Перевод по QR | - | 11 млн [10], [11] |
| Оплата по биометрии | - | 660 тыс [10], [11] |
| Оплата банковскими картами | - | 163 млн [12] |
| Перевод международный | - | 4.7 тысяч [14] |
* Рассчитано на основе DAU = 42.5 млн и 1 сессии на активного пользователя в день.
| Тип запроса | Средний RPS (Операций в сутки / 86 400) | Пиковый RPS (тройной средний RPS) |
|---|---|---|
| Авторизация | 16 | 48 |
| Получение баланса | 1230 | 3689 |
| Получение чека | 221 | 664 |
| История платежей | 147 | 441 |
| Открытие вкладов | 0.02 | 0.06 |
| Открытие кредит | 0.6 | 1.8 |
| Открытие ипотек | 0.04 | 0.12 |
| Перевод по СБП | 584 | 1752 |
| Перевод по QR | 127 | 381 |
| Оплата по биометрии | 8 | 24 |
| Оплата банковскими картами | 1887 | 5661 |
| Перевод международный | 0.05 | 0.15 |
| ИТОГО | 4221 | 12662 |
Запросов в секунду (RPS) составляет 221.
Также средний размер одного чека — 60 КБ = 61440 байт.
Тогда объём данных в секунду:
221 запросов/сек * 61440 байт = 13 578 240 байт/с ≈ 108.6 Мбит/с — пиковое потребление.
Суммарный суточный объём данных:
13 578 240 байт/с * 86 400 сек = 1 173 159 936 000 байт ≈ 1 173 ГБ/сутки ≈ 1.17 ТБ/сутки.
| Домен | Функционал | Средний RPS | Пиковый RPS | Распределение нагрузки, % |
|---|---|---|---|---|
wallet |
Получение баланса, чела и истории платежей | 1598 | 4794 | 37,9 |
transaction |
Открытие вкладов, кредитов, вкладов; оплата по СБП, QR, биометрии, банковскими картами, международные | 2607 | 7818 | 62,1 |
api |
Весь остальной функционал, в частности, авторизация |
* Составлено на основе таблицы из раздела "Расчет нагрузки".
Группировка ДЦ по регионам (приложение B). Рассматривались города-миллионники.
| Город | Население | Доля от РФ | DAU (общий DAU * доля от РФ) |
|---|---|---|---|
| Москва | ~13.1 млн | 9.0% | 3 825 000 |
| Нижний Новгород | ~1.2 млн | 0.8% | 340 000 |
| Воронеж | ~1.0 млн | 0.7% | 297 500 |
| Волгоград | ~1.0 млн | 0.7% | 297 500 |
| Итого | ~16.4 млн | 11.2% | 4 760 000 |
| Город | Население | Доля от РФ | DAU |
|---|---|---|---|
| Санкт-Петербург | ~5.6 млн | 3.8% | 1 615 000 |
| Итого | ~5.6 млн | 3.8% | 1 615 000 |
| Город | Население | Доля от РФ | DAU |
|---|---|---|---|
| Екатеринбург | ~1.5 млн | 1.1% | 467 500 |
| Челябинск | ~1.2 млн | 0.8% | 340 000 |
| Уфа | ~1.2 млн | 0.8% | 340 000 |
| Пермь | ~1.0 млн | 0.7% | 297 500 |
| Итого | ~4.9 млн | 3.4% | 1 445 000 |
| Город | Население | Доля от РФ | DAU |
|---|---|---|---|
| Новосибирск | ~1.6 млн | 1.1% | 467 500 |
| Красноярск | ~1.2 млн | 0.8% | 340 000 |
| Омск | ~1.1 млн | 0.8% | 340 000 |
| Итого | ~3.9 млн | 2.7% | 1 147 500 |
| Город | Население | Доля от РФ | DAU |
|---|---|---|---|
| Казань | ~1.3 млн | 0.9% | 382 500 |
| Самара | ~1.2 млн | 0.8% | 340 000 |
| Итого | ~2.5 млн | 1.7% | 722 500 |
| Город | Население | Доля от РФ | DAU |
|---|---|---|---|
| Ростов-на-Дону | ~1.1 млн | 0.8% | 340 000 |
| Краснодар | ~1.1 млн | 0.8% | 340 000 |
| Итого | ~2.3 млн | 1.6% | 680 000 |
| Регион | Население | DAU | Доля от общего DAU |
|---|---|---|---|
| Центральный | ~16.4 млн | 4 760 000 | 11.2% |
| Северо-Западный | ~5.6 млн | 1 615 000 | 3.8% |
| Уральский | ~4.9 млн | 1 445 000 | 3.4% |
| Сибирский | ~3.9 млн | 1 147 500 | 2.7% |
| Приволжский | ~2.5 млн | 722 500 | 1.7% |
| Южный | ~2.3 млн | 680 000 | 1.6% |
| Город | Регион | DAU | Доля от общего DAU | Приоритет |
|---|---|---|---|---|
| Москва | Центральный | 3 825 000 | 9.0% | Критический |
| Санкт-Петербург | Северо-Западный | 1 615 000 | 3.8% | Высокий |
| Екатеринбург | Уральский | 467 500 | 1.1% | Высокий |
| Новосибирск | Сибирский | 467 500 | 1.1% | Высокий |
| Казань | Приволжский | 382 500 | 0.9% | Средний |
| Нижний Новгород | Центральный | 340 000 | 0.8% | Средний |
| Челябинск | Уральский | 340 000 | 0.8% | Средний |
| Уфа | Уральский | 340 000 | 0.8% | Средний |
| Красноярск | Сибирский | 340 000 | 0.8% | Средний |
| Омск | Сибирский | 340 000 | 0.8% | Средний |
| Самара | Приволжский | 340 000 | 0.8% | Средний |
| Ростов-на-Дону | Южный | 340 000 | 0.8% | Средний |
| Краснодар | Южный | 340 000 | 0.8% | Средний |
| Воронеж | Центральный | 297 500 | 0.7% | Низкий |
| Волгоград | Центральный | 297 500 | 0.7% | Низкий |
| Пермь | Уральский | 297 500 | 0.7% | Низкий |
RPS домена в городе = (DAU города / общий DAU) * Общий RPS домена
| ДЦ | DAU | RPS wallet |
RPS transaction |
Сумма пред. RPS |
|---|---|---|---|---|
| Москва | 3 825 000 | 144 | 235 | 379 |
| Санкт-Петербург | 1 615 000 | 61 | 99 | 160 |
| Екатеринбург | 467 500 | 18 | 29 | 47 |
| Новосибирск | 467 500 | 18 | 29 | 47 |
| Казань | 382 500 | 14 | 23 | 37 |
| Ростов-на-Дону | 340 000 | 13 | 21 | 34 |
| Город | Москва | Санкт-Петербург | Екатеринбург | Новосибирск | Казань | Ростов-на-Дону |
|---|---|---|---|---|---|---|
| Москва | - | 710 | 1 420 | 3 360 | 820 | 1 090 |
| Санкт-Петербург | 710 | - | 2 130 | 3 380 | 1 530 | 1 800 |
| Екатеринбург | 1 420 | 2 130 | - | 1 460 | 1 140 | 2 080 |
| Новосибирск | 3 360 | 3 380 | 1 460 | - | 2 350 | 3 540 |
| Казань | 820 | 1 530 | 1 140 | 2 350 | - | 1 530 |
| Ростов-на-Дону | 1 090 | 1 800 | 2 080 | 3 540 | 1 530 | - |
По примеру приложения A.
Формула: Задержка = (Расстояние * 1.7) / 200 + 10 мс, где:
- 1.7 - коэффициент увеличения пути (оптоволокно не идет по прямой),
- 200 - скорость распространения сигнала в оптоволокне (км/мс) [18],
- 10 мс - запас на сетевое оборудование и маршрутизацию.
| Город | Москва | Санкт-Петербург | Екатеринбург | Новосибирск | Казань | Ростов-на-Дону |
|---|---|---|---|---|---|---|
| Москва | - | 11 [0] | 22 | 39 | 17 | 19 |
| Санкт-Петербург | 11 [0] | - | 28 | 39 | 23 | 25 |
| Екатеринбург | 22 | 28 | - | 22 | 20 | 28 |
| Новосибирск | 39 | 39 | 22 | - | 30 | 40 |
| Казань | 17 | 23 | 20 | 30 | - | 23 |
| Ростов-на-Дону | 19 | 25 | 28 | 40 | 23 | - |
DNS - самый простой механизм балансировки, и балансировать таким образом можно любые системы, в которых доступ к сервису происходит по имени [19].
Суть балансировки на базе Anycast: мы из разных географических участков анонсируем один и тот же префикс сети. Таким образом, каждый запрос клиента будет маршрутизироваться на ближайший к нему сервер, который будет его обрабатывать [19].
Вывод: глобальная балансировка нагрузки не требуется. Все пользователи могут быть направлены в единый московский ДЦ по следующим причинам:
- 95% трафика генерируется в пределах России,
- максимальная задержка до Москвы (таблица связи между ДЦ) не превышает 40 мс даже для Дальнего Востока.
Локальная балансировка нагрузки состоит из нескольких уровней:
1. Клиентский
Инициирует HTTP/HTTPS запросы.
2. L7 Балансировщики
Разделим балансировщики по доменам, так как на L7-уровне создаётся наибольшая нагрузка на CPU.
Функции:
- SSL Termination вынесен на отдельные L7 серверы
- Маршрутизация по хостам, соответствующим доменам
| Показатель | Значение |
|---|---|
| Пиковый RPS | 12662 |
| CPS (connections per second) 1-ого CPUs (ядра) для HTTPS | 428 [22] |
| Требуется ядер | 12662 / 428 = 29.6 ≈ 30 ядер |
| Резервные ядра, чтобы нагружать не более 60% ресурсов CPU в пике | 30 ядер / 60% = 50 ядер |
| Ядра на один домен | 50 ядер / 3 = 16.7 ≈ 17 ядер на сервер |
| NGINX-сервера на домен, 8-ядерные | 17 ядер на сервер / 8 = 2.1 ≈ 3 машины |
| Схема резервирования для одного домена | N+1 (2 рабочих + 1 резервный) |
| Всего машин | 3 домена * 3 машины = 9 машин |
Размещение:
- Все L7-балансировщики размещаются в едином дата-центре в Москве с latancy равном 1.5 мс
- Балансировщики каждого домена распределяются по разным availability-зонам в рамках ДЦ
Балансировка трафика на L7-уровне с использованием Anycast BGP:
- Каждому домену назначен единый публичный IP-адрес, который анонсируется через BGP из всех availability-зон, где размещены его L7-серверы
- Маршрутизаторы дата-центра получают одинаковые BGP-анонсы, но направляют трафик к ближайшей (по метрикам) availability-зоне
- Внутри availability-зоны трафик принимается активными NGINX-серверами. В случае отказа одного из серверов, BGP-анонс остаётся активным (так как другие серверы в зоне работают), а локальный L4-балансировщик перераспределяет нагрузку между оставшимися узлами
- При полном отказе availability-зоны BGP-маршруты из этой зоны автоматически отзываются (withdrawn), и весь трафик перенаправляется на оставшиеся
4. Application Servers
Разделение по доменам:
- сервер Wallet
- сервер Transaction
- сервер API
5. Database Layer
- Master DB - для операций записи (Transaction)
- 2 реплики Replica DB - для операций чтения (Wallet, API)
Пропускная способность сети:
- Пиковый трафик: 108.6 Мбит/с * 3 = 326 Мбит/с
- 1 x 10G порт: 10 Гбит/с полезной нагрузки [20] [21]
- Требуется: 326 / 10000 Мбит/с = 0.0326 порта ≈ 1 порт
Пиковый трафик составляет менее 35% от пропускной способности 1G Ethernet и менее 4% от 10G. Следовательно, сетевой интерфейс не ограничивает производительность, и даже 1G порт будет более чем достаточен.
Ссылка: Схема таблиц в dbdiagram.io
| Название таблицы | Назначение |
|---|---|
users |
Хранит профиль пользователя: контактные данные (телефон, email), хэш пароля, ФИО, дату рождения и временные метки создания/обновления. |
accounts |
Представляет банковские счета пользователей: баланс, валюта, статус (active, blocked, closed) и привязка к пользователю (user_id). |
transactions |
Фиксирует все денежные операции между счетами: отправитель (from_account), получатель (to_account), сумма, валюта, категория (еда, транспорт), статус, описание и тип (перевод, оплата и тп.). |
receipts |
Хранит информацию о чеках или сканах, прикреплённых к транзакциям: путь к файлу, размер и временная метка. Связан с transactions. |
user_cards |
Содержит данные банковских карт: зашифрованный номер, срок действия, хэш CVV, статус и привязку к пользователю. |
deposits |
Отслеживает вклады (депозиты): сумма, процентная ставка, срок в месяцах, дата открытия и дата окончания. Привязан к счёту (account_id). |
session_cache |
Используется для временного хранения пользовательских сессий: данные в формате JSONB и время истечения сессии. |
Современные системы работают со следующими моделями консистентности [24]:
- Строгая консистентность (Strong Consistency) — все операции чтения возвращают значение самой последней успешной операции записи
- Последовательная консистентность (Sequential Consistency) — операции выполняются в том порядке, в котором они были запущены в каждом узле
- Причинная консистентность (Causal Consistency) — если операция A логически предшествует операции B, то все узлы увидят их в этом порядке
- Итоговая консистентность (Eventual Consistency) — при отсутствии обновлений все узлы системы в конечном итоге сходятся к одному значению
| Таблица | Модель консистентности | Обоснование, пример |
|---|---|---|
users |
Строгая | После смены email или пароля все последующие запросы должны немедленно видеть новое значение |
accounts |
Строгая | При переводе средств чтение баланса должно отражать самую последнюю успешную транзакцию |
transactions |
Строгая | После успешного завершения операции все последующие чтения должны возвращать её как существующую |
receipts |
Итоговая | Чек — подтверждающий документ, не участвующий в логике списания |
user_cards |
Строгая | Активная карта без привязки к пользователю — угроза безопасности |
deposits |
Строгая | Данные должны быть точными и синхронизированы с accounts |
session_cache |
Итоговая | Сессии временные, могут быть утеряны без ущерба для данных |
| Таблица | Размер таблицы, байт | Расчеты |
|---|---|---|
users |
165 | user_id(4) + phone(16) + email(30) + password_hash(60) + first_name(15) + last_name(20) + birth_date(4) + created_at(8) + updated_at(8) |
accounts |
40 | account_id(4) + user_id(4) + balance(8) + currency(4) + status(4) + timestamps(16) |
transactions |
150 | ids(12) + amount(8) + currency(4) + category(15) + status(10) + description(50) + type(10) + merchant(30) + timestamp(8) |
receipts |
120 | ids(8) + file_path(100) + file_size(4) + timestamp(8) |
user_cards |
141 | card_id(4) + user_id(4) + card_number_encrypted(50) + expiry(5) + cvv_hash(60) + status(10) + timestamp(8) |
deposits |
37 | ids(8) + amount(8) + rate(5) + term(4) + timestamps(12) |
session_cache |
216 | session_id(4) + user_id(4) + data(jsonb, 200) + expires(8) |
| Таблица | Размер данных |
|---|---|
users |
110 млн * 165 байт = 17 ГБ |
accounts |
Пусть минимум один счет у клиента: 110 млн * 40 байт = 4 ГБ |
transactions |
На основе расчетов объема хранилища: 125 транзакций в месяц * 12 месяцев * 34 года * 84.4 млн * 150 байт = 587 ТБ |
receipts |
Если не создавать для каждой транзакции чек, то пусть коэфф. создания будет равен 1 раз к 14 дням, то объем равен: 2 чека месяц * 12 месяцев * 34 года * 84.4 млн * 120 байт = 7.6 ТБ |
user_cards |
Пусть минимум одна карта у клиента: 110 млн * 141 байт = 14 ГБ |
deposits |
(2025 г. - 1981 г.) * (530 тыс (8 месяцев [15]) / 8 * 12) * 37 байт = 1.2 ГБ |
session_cache |
Активные сессии одновременно 550 тыс * 216 байт = 113 МБ |
| Таблица | Средняя нагрузка (QPS) на запись * | Средняя нагрузка (QPS) на чтение * |
|---|---|---|
users |
1/182 дней / 86400 ≈ 7 | 2606 (оплата) + ~1 (открытие услуг) = 2607 |
accounts |
~2606 (оплата = изменение счета) | 1230 (получение баланса) |
transactions |
2606 (изменение status'а y оплаты) | 2606 (оплата) + 147 (история платежей) |
receipts |
1 | 221 (получения чека) |
user_cards |
1 | 2606 (оплата) |
deposits |
1 | 2/30 дней / 86400 ≈ 8 |
session_cache |
1 | 16 (авторизация) |
* Значения основаны на таблице RPS действий.
Ссылка: Физическая схема таблиц в dbdiagram.io
| Таблица | Денормализация | Индексы | Шардирование | СУБД | Резервное копирование, тип и частота |
|---|---|---|---|---|---|
| users | total_balance (decimal) |
phone, email |
Нет | PostgreSQL | Полный + WAL Ежемесячно + непрерывно |
| accounts | user_phone, user_full_name (text) |
user_id, status, user_phone, user_full_name |
Нет | PostgreSQL | Полный + WAL Ежедневно + непрерывно |
| transactions_credit | to_user_name, from_user_name (text) |
(to_account, created_at), status, category |
Вертикальное + горизонтальное | PostgreSQL | Полный + консистентные снепшоты + WAL Ежедневно + непрерывно |
| transactions_debit | from_user_name, to_user_name (text) |
(from_account, created_at), status, category |
Вертикальное + горизонтальное | PostgreSQL | Полный + консистентные снепшоты + WAL Ежедневно + непрерывно |
| transactions_global_index | Нет | created_at, account_id, (shard_type, account_id) |
Нет | PostgreSQL | Полный + WAL Ежедневно + непрерывно |
| receipts | transaction_amount, transaction_date |
transaction_id, transaction_date |
Нет | PostgreSQL | Полный Ежемесячно |
| user_cards | user_phone, user_full_name (text) |
user_id, status, user_phone |
Нет | PostgreSQL | Полный + WAL Еженедельно + непрерывно |
| deposits | current_balance (decimal) |
account_id |
Нет | PostgreSQL | Полный Ежемесячно |
| session_cache | Нет | user_id |
Нет | Redis | RDB снепшоты + AOF лог Ежечасно + непрерывно |
1. users
Денормализация:
- total_balance типа decimal(15,2) — быстрый доступ к общему балансу без JOIN с
accounts
Индексы:
- phone — для авторизации по телефону
- email — для авторизации по email
Шардирование: отсутствует
СУБД: PostgreSQL
Схема резервного копирования:
- Тип бэкапа: Полный + WAL
- Частота: Ежемесячно + непрерывно
2. accounts
Денормализация:
- user_phone типа text — данные пользователя для отчетов без JOIN с
users - user_full_name типа text — —//—
Индексы:
- user_id — поиск всех счетов пользователя
- status — фильтрация по статусу счета: active, blocked, closed
- user_phone — быстрый поиск владельца по телефону
- user_full_name — —//— по имени
Шардирование: отсутствует
СУБД: PostgreSQL
Схема резервного копирования:
- Тип бэкапа: Полный + WAL
- Частота: Ежедневно + непрерывно
3. transactions_credit
Денормализация:
- to_user_name типа text — данные для отчетов без JOIN с
users - from_user_name типа text — —//—
Индексы:
- (to_account, created_at) — история операций по счету
- status — фильтрация по статусу операций: pending, completed, failed
- category — аналитика по категориям пополнений
Шардирование:
- вертикальный (доменный):
transactionsшардируется по типу операций — все зачисления на счет находятся в одном домене - горизонтальный: максимальный размер таблицы 32 ТБ [25], однако в шарде оптимально хранить около 1 ТБ, но не более 2 ТБ [0], поэтому таблицу разнесем на 587 ТБ / 1 ТБ = 587 частей по ключу
to_account
СУБД: PostgreSQL
Схема резервного копирования:
- Тип бэкапа: Полный + консистентные снепшоты* через WAL
- Частота: Ежедневно + непрерывно
* Чтобы избежать случая когда:
- В t времени первый шард бэкапится, когда, например, операция снятия уже в бэкапе
- В t+n времени второй шард бэкапится, когда, например, операция пополнения еще не в бэкапе
- Получаем, что при восстановлении сняли деньги, но другой не получил
Поэтому алгоритм:
- Фиксируем точку консистентности
- Бэкапим каждый шард независимо
- При восстановлении применяем WAL до зафиксированной точки
4. transactions_debit
Денормализация:
- from_user_name типа text — данные для отчетов без JOIN с
users - to_user_name типа text — —//—
Индексы:
- (from_account, created_at) — история операций по счету
- status — фильтрация по статусу операций
- category — аналитика по категориям расходов
Шардирование:
- вертикальное (доменное):
transactionsшардируется по типу операций — все списания со счета находятся в одном домене - горизонтальное: максимальный размер таблицы 32 ТБ [25], однако в шарде оптимально хранить около 1 ТБ, но не более 2 ТБ [0], поэтому таблицу разнесем на 587 ТБ / 1 ТБ = 587 частей по ключу
from_account
СУБД: PostgreSQL
Схема резервного копирования: аналогично transactions_credit
5. transactions_global_index
Глобальный индекс для поиска транзакций в нужной шарде. shard_type типа text: 'credit' или 'debit' — указывает в какой таблице искать.
Денормализация: отсутствует
Индексы:
- created_at — поиск транзакций за период
- account_id — поиск всех транзакций пользователя
- (shard_type, account_id) — поиск транзакций определенного типа
Шардирование: отсутствует
СУБД: PostgreSQL
Схема резервного копирования:
- Тип бэкапа: Полный + WAL
- Частота: Ежедневно + непрерывно
6. receipts
Денормализация:
- transaction_amount типа decimal(15,2) — данные для отображения без JOIN с
transactions - transaction_date типа timestamp — —//—
Индексы:
- transaction_id — поиск чека по транзакции
- transaction_date — поиск чеков за период
Шардирование: отсутствует
СУБД: PostgreSQL
Схема резервного копирования:
- Тип бэкапа: Полный
- Частота: Ежемесячно
- Хранилище: облачный S3
7. user_cards
Денормализация:
- user_phone типа text — для быстрого отображения без JOIN с
users - user_full_name типа text — —//—
Индексы:
- user_id — поиск всех карт пользователя
- status — фильтрация по статусу карты: active, blocked, expired
- user_phone — быстрый поиск по телефону владельца
Шардирование: отсутствует
СУБД: PostgreSQL
Схема резервного копирования:
- Тип бэкапа: Полный + WAL
- Частота: Еженедельно + непрерывно
8. deposits
Денормализация:
- current_balance типа decimal(15,2) — данные для отображения без JOIN с
accounts
Индексы:
- account_id — поиск депозитов по счету
Шардирование: отсутствует
СУБД: PostgreSQL
Схема резервного копирования:
- Тип бэкапа: Полный
- Частота: Ежемесячно
9. session_cache
Денормализация: отсутствует
Индексы:
- user_id — поиск сессии по пользователю
Шардирование: отсутствует
СУБД: Redis
Схема резервного копирования:
- Тип бэкапа: RDB снепшоты + AOF лог
- Частота: Ежечасно + непрерывный
| Алгоритм | Область применения | Мотивация |
|---|---|---|
| Ключ идемпотентности: 1. Клиент генерирует уникальный ключ для каждой операции 2. При первом запросе в поле БД устанавливается в поле idempotency_key ключ, переданных клиентом3. При повторном запросе с тем же ключом возвращается существующий результат, новый не создается |
Любые финансовые операции списания/зачисления: начисление процентов по вкладам deposits, переводы transactions |
Гарантия, что операция выполнится ровно один раз даже при повторных вызовах |
| Двусвязные коммиты (2PC) | Операции в рамках одной СУБД, затрагивающие несколько таблиц. Например, при переводе денег между клиентами: изменение баланса в accounts у обоих клиентов + добавление строки списывания и пополнения в transactions соответственно |
Обеспечение согласованности данных в транзакциях, выходящих за пределы одной системы, сохранить семантику единой атомарной транзакции [26] |
| Технология | Область применения | Мотивационная часть |
|---|---|---|
| Go | микросервисы Backend'а wallet, transaction, api |
Высокая производительность при 12 662 RPS, эффективное управление памятью, асинхронность (встроенные горутины для параллельной обработки транзакций) |
| Kotlin | Мобильные приложения (Android) | Стабильность, богатая экосистема библиотек |
| Swift | Мобильные приложения (iOS) | Интеграция с iOS экосистемой |
| TypeScript | Web-интерфейс | Статическая типизация, интеграция с React и Next.js |
| PostgreSQL | Данные users, accounts, transactions, deposits |
ACID-транзакции для финансовых операций, поддержка шардинга и 2PC |
| Redis | Кэш сессий session_cache |
In-memory хранение для горячих данных (550 тыс активных сессий), автоматическое удаление просроченных сессий (TTL) |
| NGINX | L7 балансировка | SSL Termination для HTTPS, маршрутизация по доменам |
| Kubernetes | Оркестрация микросервисов | Автомасштабирование под нагрузкой, управление серверами балансировки |
| Prometheus | Мониторинг | Сбор метрик с балансировщиков и микросервисов |
| Grafana | Визуализация метрик | Дашборды для мониторинга RPS, задержек, ошибок транзакций |
| ClickHouse | Аналитика и отчетность | Реалтайм-аналитика транзакций, отчеты ЦБ РФ, ML-модели для выявления мошенничества |
| HashiCorp Vault | Управление секретами | Безопасное хранение ключей шифрования, токенов API, паролей БД |
| Компонент системы | Способы резервирования |
|---|---|
| L7 Балансировщики (NGINX) | - Распределение: Active-Active кластер с N+1 репликами по трём availability-зонам с Anycast BGP балансировкой трафика [27] - Отказоустойчивость: Автоматическое переключение трафика при отказе зоны - Защита: Rate limiting для предотвращения перегрузки - Мониторинг: Health checks с автоматическим исключением и рестартом неработающих нод |
| Сервера приложений (микросервисы) | - Оркестрация: Kubernetes ReplicaSet с N+1 по трём availability-зонам репликами на сервис - Управление нагрузкой: Автомасштабирование по метрикам CPU и памяти - Безопасное завершение: Graceful Shutdown для сохранения целостности данных - Деградация: Graceful Degradation при частичных отказах - Самовосстановление: Health checks с автоматическим рестартом контейнеров |
| Базы данных PostgreSQL | - Оркестрация: Patroni для автоматического управления кластером - Доступность: реверс-проксёй Odyssey обслуживать много клиентов, используя небольшой пул соединений к БД - Репликация: Master + 2 реплики - Резервное копирование: WAL + полные снепшоты |
| Кэш Redis (сессии) | - Оркестрация: Redis Sentinel для мониторинга и автоматического failover - Кластеризация: Redis Cluster с архитектурой master-slave - Синхронизация: Репликация в реальном времени между узлами - Персистентность: Комбинирование RDB и AOF для сохранения данных |
| Дата-центры | - Инфраструктура: Tier-4 архитектура - Сети: Избыточная схема сети - Энергоснабжение: Схема подачи питания - Охлаждение: Избыточная система охлаждения (приложение D) - География: Стратегическое физическое положение для минимизации рисков |
Дополнительные механизмы обеспечения надежности:
- Мониторинг: Комплексный сбор метрик через Prometheus с визуализацией в Grafana и настройка Alert Manager в случае аварий
- Аналитика: Централизованное логирование с помощью сквозной трассировки Trace ID для выявления и анализа инцидентов
- Тестирование: Регулярные chaos-тесты для проверки отказоустойчивости и учения команды по аварийным ситуациям
Для Go сервисов используем оценку: 1000 RPS на 1 ядро CPU [28].
| Компонент | Средний RPS | Пиковый RPS (×3) | Требуется ядер CPU | RAM на экземпляр | Назначение |
|---|---|---|---|---|---|
| Микросервис Transaction | 2 607 | 7 818 | ⌈7818 / 1000⌉ = 8 | 2 ГБ | Обработка финансовых транзакций, требует строгой консистентности |
| Микросервис Wallet | 1 598 | 4 794 | ⌈4794 / 1000⌉ = 5 | 2 ГБ | Получение баланса, истории платежей, умеренная нагрузка |
| Микросервис API | 16 | 48 | ⌈48 / 1000⌉ = 1 | 1 ГБ | Авторизация и вспомогательные операции, низкая нагрузка |
Для NGINX используем оценку: 428 CPS (connections per second) на 1 ядро CPU для HTTPS [22].
| Компонент | Пиковый RPS | Требуется ядер CPU | RAM на экземпляр | Назначение |
|---|---|---|---|---|
| NGINX L7 (всего) | 12 662 | ⌈12662 / 428⌉ = 30 ядер С учетом 60% загрузки: 50 ядер |
4 ГБ | SSL Termination, маршрутизация по доменам |
| NGINX на домен | ~4 221 | 17 ядер на домен | 4 ГБ | Распределение по 3 доменам (wallet, transaction, api) |
Для PostgreSQL используем оценку: 200 операций/сек на 1 ядро CPU.
Исходные данные [см. раздел 5]:
- Объём данных на диске: 594 ТБ
- Нагрузка на чтение: 9 425 QPS
- Нагрузка на запись: 5 222 QPS
- Суммарная нагрузка: 14 647 QPS
Рекомендации:
- Если размер данных на диске >1 ТБ, то рекомендуемый размер RAM >256 ГБ [30]
| Компонент | Нагрузка QPS | Требуется ядер CPU | RAM | Назначение |
|---|---|---|---|---|
| PostgreSQL Master | 5 222 (запись) | ⌈5222 / 200⌉ = 27 ядер → 32 ядра | 512 ГБ | Операции записи, требуется высокая производительность |
| PostgreSQL Replica 1 | 4 712 (чтение) | ⌈4712 / 200⌉ = 24 ядра | 512 ГБ | Чтение для домена wallet |
| PostgreSQL Replica 2 | 4 713 (чтение) | ⌈4713 / 200⌉ = 24 ядра | 512 ГБ | Чтение для домена api и резерв |
Исходные данные [см. раздел 5 и 6]:
- transactions_credit: 587 ТБ, разбито на 587 шардов по 1 ТБ каждый
- transactions_debit: 587 ТБ, разбито на 587 шардов по 1 ТБ каждый
- receipts: 7.6 ТБ
- Итого: 1181.6 ТБ данных, 1174 шарда + receipts
Расчёт серверов для хранения шардов:
- Каждый шард содержит ~1 ТБ данных (с учетом индексов и служебных данных ~1.2 ТБ)
- На одном сервере размещаем до 8 шардов (8 ТБ данных + запас для WAL, индексов, временных файлов = ~10 ТБ на сервер)
- Требуется серверов: ⌈1174 / 8⌉ = 147 серверов для шардов
- Для receipts требуется: ⌈7.6 / 8⌉ = 1 сервер
- Итого: 148 серверов для хранения исторических данных
Рекомендации для архивных серверов:
- Исторические данные редко запрашиваются, поэтому можно использовать менее производительные, но более ёмкие сервера
- Для отказоустойчивости требуется репликация: каждая реплика хранит копию шардов
- Используем конфигурацию с большим объёмом дисков, но меньшим количеством CPU и RAM
| Компонент | Объём данных | Количество шардов | Серверов (основных) | Серверов (реплик) | CPU на сервер | RAM на сервер | Назначение |
|---|---|---|---|---|---|---|---|
| PostgreSQL Shards (credit) | 587 ТБ | 587 | 74 | 74 | 32 ядра | 128 ГБ | Хранение исторических транзакций зачислений, низкая нагрузка |
| PostgreSQL Shards (debit) | 587 ТБ | 587 | 74 | 74 | 32 ядра | 128 ГБ | Хранение исторических транзакций списаний, низкая нагрузка |
| PostgreSQL Receipts | 7.6 ТБ | 1 | 1 | 1 | 32 ядра | 128 ГБ | Хранение исторических чеков, низкая нагрузка |
| ИТОГО | 1181.6 ТБ | 1175 | 149 | 149 | - | - | - |
Исходные данные [см. раздел 5]:
- Объём данных: 113 МБ (550 тыс активных сессий × 216 байт)
- Нагрузка на чтение: 16 QPS
- Нагрузка на запись: 1 QPS
- Суммарная нагрузка: 17 QPS
Допущения:
- RPS Redis равен 35 600 единицам [29]
| Компонент | Нагрузка QPS | Требуется ядер CPU | RAM | Назначение |
|---|---|---|---|---|
| Redis Cluster | 17 | 1 ядро (с большим запасом) | 2 ГБ | Кэш сессий, низкая нагрузка, но требуется отказоустойчивость |
| Компонент | Нагрузка | Требуется ядер CPU | RAM | Назначение |
|---|---|---|---|---|
| Prometheus | Сбор метрик со всех сервисов | 4 ядра | 16 ГБ | Постоянная запись временных рядов, агрегация данных |
| Grafana | Визуализация метрик | 2 ядра | 8 ГБ | Рендеринг дашбордов, запросы к Prometheus |
| Компонент | Нагрузка | Требуется ядер CPU | RAM | Назначение |
|---|---|---|---|---|
| ClickHouse | Аналитика транзакций, отчеты ЦБ РФ | 8 ядер | 64 ГБ | Реалтайм-аналитика, ML-модели для антифрода |
| Компонент | Нагрузка | Требуется ядер CPU | RAM | Назначение |
|---|---|---|---|---|
| HashiCorp Vault | Управление секретами | 2 ядра | 8 ГБ | Хранение ключей шифрования, токенов API, паролей БД |
| Сервис | Пиковая нагрузка | CPU (ядер) | RAM | Сеть |
|---|---|---|---|---|
| NGINX L7 (всего) | 12 662 RPS | 50 | 36 ГБ | 326 Мбит/с |
| Микросервис Transaction | 7 818 RPS | 8 | 6 ГБ | - |
| Микросервис Wallet | 4 794 RPS | 5 | 6 ГБ | - |
| Микросервис API | 48 RPS | 1 | 2 ГБ | - |
| PostgreSQL Master | 5 222 QPS | 32 | 512 ГБ | - |
| PostgreSQL Replica × 2 | 9 425 QPS | 48 (24×2) | 1024 ГБ (512×2) | - |
| PostgreSQL Shards (основные) | Низкая (архив) | 4 768 (32×149) | 19 ТБ (128×149) | - |
| PostgreSQL Shards (реплики) | Низкая (архив) | 4 768 (32×149) | 19 ТБ (128×149) | - |
| Redis Cluster | 17 QPS | 1 | 2 ГБ | - |
| Prometheus | Сбор метрик | 4 | 16 ГБ | - |
| Grafana | Визуализация | 2 | 8 ГБ | - |
| ClickHouse | Аналитика | 8 | 64 ГБ | - |
| HashiCorp Vault | Секреты | 2 | 8 ГБ | - |
| ИТОГО | - | 9 646 | 38.7 ТБ | 326 Мбит/с |
Как мы видим наши сервисы не умещаются в физические сервера и требуют горизонтального масштабирования.
Был выбран гибридный подход поскольку:
- Полностью собственное железо было бы избыточно дорогим для некритичных сервисов (ClickHouse, Vault, CI/CD), которые не требуют максимальной производительности и могут работать на виртуальных машинах
- Полностью облачное решение не обеспечивает необходимую производительность для критически важных компонентов (PostgreSQL, NGINX, Redis), которые требуют минимального overhead и максимальной производительности bare-metal серверов
- Гибридный подход позволяет оптимизировать затраты: размещать критичные высоконагруженные сервисы на собственном железе для максимальной производительности, а некритичные сервисы — на арендованных виртуальных машинах для экономии средств
1. Stateless сервисы в Kubernetes (на собственном железе):
- Микросервисы (Transaction, Wallet, API) - запускаются в Kubernetes для автомасштабирования и отказоустойчивости
- Prometheus, Grafana - мониторинг в Kubernetes
- Kubernetes Worker Nodes - размещаются на собственном железе для обеспечения производительности
2. Stateful сервисы на bare-metal:
- PostgreSQL (Master + 2 Replica) - критически важная БД, требует максимальной производительности и минимального overhead
- PostgreSQL Shards (149 основных + 149 реплик) - хранилище исторических данных, низкая нагрузка, но большой объём данных
- Redis Cluster - in-memory БД, требует низкой задержки
- NGINX L7 балансировщики - высоконагруженные, требуют минимального overhead
3. Вспомогательные сервисы на арендованных виртуальных машинах (Hetzner):
- ClickHouse - аналитика, не критична для основной работы системы
- HashiCorp Vault - управление секретами, низкая нагрузка
| Название | Конфигурация | CPU (Ядра) | RAM | Количество | Покупка (5 лет) | Аренда/мес |
|---|---|---|---|---|---|---|
| PostgreSQL Master | 2×6338/16×32GB/2×NVMe4T/2×25Gb/s | 128 | 512 GB | 1 | $18 500 | $308 |
| PostgreSQL Replica | 2×6338/16×32GB/2×NVMe4T/2×25Gb/s | 128 | 512 GB | 2 | $37 000 | $616 |
| PostgreSQL Shards | 2×6338/4×32GB/2×NVMe10T/2×25Gb/s | 32 | 128 GB | 149 | $2 235 000 | $37 250 |
| PostgreSQL Shards Repl | 2×6338/4×32GB/2×NVMe10T/2×25Gb/s | 32 | 128 GB | 149 | $2 235 000 | $37 250 |
| NGINX L7 | 2×6338/4×32GB/2×NVMe1T/2×25Gb/s | 128 | 128 GB | 9 | $126 000 | $2 100 |
| Kubernetes Master | 2×6338/8×32GB/2×NVMe2T/2×25Gb/s | 128 | 256 GB | 3 | $45 000 | $750 |
| Kubernetes Worker | 2×6338/16×32GB/2×NVMe4T/2×25Gb/s | 128 | 512 GB | 3 | $55 500 | $925 |
| Redis Cluster | 2×6338/4×32GB/2×NVMe512Gb/2×25Gb/s | 128 | 128 GB | 3 | $30 000 | $500 |
| Итого | - | 9 536 | 38.7 ТБ | 319 | $4 787 000 | $79 699 |
Примечание:
- Серверы для шардов используют менее производительную конфигурацию (32 ядра вместо 128, 128 ГБ RAM вместо 512 ГБ), но с большим объёмом дисков (10 ТБ вместо 4 ТБ), так как исторические данные редко запрашиваются и не требуют высокой производительности.
- Стоимость одного сервера шардов: $15 000 (149 основных + 149 реплик = 298 серверов × $15 000 = $4 470 000, включено в общую сумму).
| Название | Хостинг | Конфигурация | CPU (Ядра) | RAM | Количество | Аренда/мес |
|---|---|---|---|---|---|---|
| ClickHouse | Hetzner | i5-13500/64GB/2×NVMe512Gb/2×10Gb/s | 14 | 64 GB | 1 | $80 |
| HashiCorp Vault | Hetzner | i5-13500/32GB/2×NVMe256Gb/2×10Gb/s | 14 | 32 GB | 1 | $50 |
| Итого аренда | - | - | 42 | 128 GB | 2 | $130 |
| Категория | Серверов | CPU (Ядра) | RAM | Покупка (5 лет) | Аренда/мес |
|---|---|---|---|---|---|
| Bare-metal | 319 | 9 536 | 38.7 ТБ | $4 787 000 | $79 699 |
| Аренда VM | 3 | 42 | 128 ГБ | $7 800 | $130 |
| ВСЕГО | 322 | 9 578 | 38.8 ТБ | $4 794 800 | $79 879 |
Для сервисов в оркестрации Kubernetes указываем requests и limits для CPU и RAM, а также количество реплик.
Пусть:
- CPU requests = требуемое количество ядер / количество реплик
- CPU limits = CPU requests × 2 (запас для пиковых нагрузок, но без throttling)
- RAM requests = базовое потребление памяти на экземпляр
- RAM limits = RAM requests × 2 (защита от утечек памяти)
| Сервис | CPU/r | CPU/l | RAM/r | RAM/l | Кол. реплик | Обоснование |
|---|---|---|---|---|---|---|
| Микросервис Transaction | 3 | 6 | 2 GB | 4 GB | 3 | Высокая нагрузка (7818 RPS), требуется отказоустойчивость N+1 |
| Микросервис Wallet | 2 | 4 | 2 GB | 4 GB | 3 | Средняя нагрузка (4794 RPS), требуется отказоустойчивость N+1 |
| Микросервис API | 1 | 2 | 1 GB | 2 GB | 2 | Низкая нагрузка (48 RPS), достаточно 2 реплик |
| Сервис | CPU/r | CPU/l | RAM/r | RAM/l | Кол. реплик | Назначение |
|---|---|---|---|---|---|---|
| Prometheus | 2 | 4 | 8 GB | 16 GB | 2 | Сбор метрик со всех сервисов, требуется отказоустойчивость |
| Grafana | 1 | 2 | 4 GB | 8 GB | 2 | Визуализация метрик, требуется отказоустойчивость |
| Сервис | CPU/r (всего) | CPU/l (всего) | RAM/r (всего) | RAM/l (всего) | Кол. реплик (всего) |
|---|---|---|---|---|---|
| Микросервис Transaction | 12 | 24 | 6 GB | 12 GB | 3 |
| Микросервис Wallet | 7.5 | 15 | 6 GB | 12 GB | 3 |
| Микросервис API | 2 | 4 | 2 GB | 4 GB | 2 |
| Prometheus | 4 | 8 | 16 GB | 32 GB | 2 |
| Grafana | 2 | 4 | 8 GB | 16 GB | 2 |
| ИТОГО | 27.5 | 55 | 38 GB | 76 GB | 12 |
Распределение по Worker Nodes:
- 3 Worker Nodes с конфигурацией 128 ядер CPU / 512 GB RAM каждая
- Общая емкость: 384 ядра CPU / 1536 GB RAM
- Использование: 27.5 ядер (7.2%) / 38 GB (2.5%) - большой запас для масштабирования
- Экспертная оценка, опыт Александра Быкова :)
- На-Связи.ru - Статистика Сбербанка на 2018 год
- Амурская правда - Статистика пользователей Сбербанк Онлайн
- VK - Статистика месячной аудитории на 2023 год
- Habr - 110 тысяч новых сессий в минуту: архитектура Сбербанк Онлайн
- Bankinform - Клиентская база Сбербанка в 2025 году
- SberBank Investor Relations - Финансовая отчетность за 7 месяцев 2025 года
- В каких странах есть офисы Сбербанка? - Рамблер/личные финансы
- Российские банки за рубежом: какие банки есть в Европе, США
- Как часто пользователи взаимодействуют с приложением?
- Центробанк РФ - Заседание по финстабильности, 28 августа 2025
- Интерфакс - Бизнес новости, 28 августа 2025
- Клерк.ру: Последние изменения для бухгалтеров, 10 июня 2025
- ЦБ РФ: Аналитический обзор Системы быстрых платежей, 2025 год
- ВТБ сообщает о семикратном росте международных переводов, октябрь 2024
- Актуальные события в банковской сфере, 28 июля 2025 г.
- Finance.Mail.ru: Выдача потребительских кредитов в России в июле выросла на 13%
- РБК Недвижимость: Новости рынка недвижимости
- Занимательный оптокабель
- Сравнительный анализ методов балансировки трафика. HighLoad++ Junior / Хабр
- What is the difference between 10G and 2.5G ports?- Walsun
- Типы портов коммутатора
- Testing the Performance of NGINX and NGINX Plus Web Servers – NGINX Community Blog
- HAProxy Kubernetes Ingress Controller Twice as Fast with Lowest CPU vs. Four Competitors | OpsMatters
- Консистентность данных: что это и почему она так важна
- Краткий обзор возможностей PostgreSQL | PostgreSQL
- Распределённые транзакции в микросервисах: от SAGA до Two‑Phase Commit / Хабр
- Кластеризация для обеспечения отказоустойчивости | Microsoft Learn
- Сколько нужно ядер cpu, чтобы выдержать 30k+ rps? / Хабр
- Нагрузочный поединок: Tarantool 2.10 vs Redis 7.0.5 / Хабр
- Все, что нужно PostgreSQL: быстрые диски, дорогой процессор и терабайты RAM / Хабр







