Завдання №2
Конструювання програмного забезпечення
Мета
Спроєктувати зберігання даних для системи із Завдання №1: обрати бази даних під конкретні дані й запити, розрахувати, скільки машин вони потребують, і спланувати реплікацію, балансування навантаження та кешування.
Беріть числа із Завдання №1: RPS на читання і запис, обсяг даних за 5 років, співвідношення читання до запису. Якщо за цей час вони змінилися, оновіть їх і поясніть чому.
Орієнтири для розрахунків
Доповнюють орієнтири із Завдання №1:
| Величина | Орієнтир |
|---|---|
| Одна машина БД | 10k RPS читань або 1k RPS записів, 50 ТБ SSD, 1 ТБ RAM |
| Один вузол кешу в RAM (Redis) | порядку 100 тис. операцій на секунду |
| Звернення до пам’яті | 100 нс |
| Запит туди й назад у межах дата-центру | 0.5 мс |
| Позиціювання головки HDD | 10 мс |
| Навантаження на БД з кешем | читання × (1 − частка влучань у кеш) |
| Пікове навантаження | у 2–3 рази більше за середнє |
| Реплікація | кожен запис зберігається у 3 копіях |
Розминка: знайдіть помилки 🕵️
Студент проєктує зберігання для хостингу текстів із лекції (на кшталт Pastebin):
- 1 млн нових текстів на день по 10 кБ;
- 12 RPS на запис і 120 RPS на читання;
- за 5 років — 1.8 млрд текстів, або 18 ТБ;
- нефункціональна вимога: завантажені тексти не повинні зникати.
Його рішення:
- Масштабування. 18 ТБ — це багато, тому розбиваємо тексти на 18 шардів по 1 ТБ, кожен на окремому сервері.
- Тип БД. Текст завжди читають за коротким посиланням, тобто за ключем, тож метадані можна тримати в key-value сховищі або в реляційній БД з індексом за ключем.
- Кеш. Щоб читання були швидкими, кешуємо в Redis усі тексти.
- Балансування. Балансувальник рівномірно розподіляє всі запити, зокрема записи, між трьома репліками БД.
- Надійність. Щоб записи були швидкими, пишемо текст спершу в Redis, а в БД переносимо раз на годину.
В одному рядку все правильно, у решті — помилки. Знайдіть їх, перш ніж відкривати відповідь.
- ❌ Шардування не потрібне. 120 RPS читань і 12 RPS записів — це ≈ 1% можливостей однієї машини (10k і 1k), а 18 ТБ вміщаються на її 50 ТБ SSD. Потрібні не шарди, а репліки — для доступності й збереження даних. А ще краще класти самі тексти в об’єктне сховище (на кшталт S3), а в БД тримати лише метадані: ключ, автора, дату, термін дії.
- ✅ Правильно: вибір типу БД випливає із запиту, який вона обслуговує.
- ❌ Кешувати все — дорого й марно. 18 ТБ RAM коштують ≈ $180 тис. і займуть 18 машин. Здебільшого читають свіжі тексти: за день їх з’являється 10 ГБ, і якщо кешувати найпопулярніші 20%, вистачить ≈ 2 ГБ.
- ❌ Записи йдуть лише на лідера. У реплікації «лідер — послідовники» репліки приймають тільки читання. Балансувати можна читання, а записи — ні.
- ❌ Кеш не є джерелом правди. Якщо вузол Redis впаде між перенесеннями, тексти за годину можуть загубитися, а це прямо порушує вимогу «завантажені тексти не повинні зникати». Спершу запис у БД, потім — у кеш.
Етапи
1. Дані та запити
Базу даних обирають під запити, тому почніть із них.
Випишіть 3–6 основних сутностей і заповніть таблицю:
Сутність Розмір запису Записів за 5 років Обсяг Читань/с Записів/с … … … … … … Випишіть основні запити до даних і вимоги до них:
Запит Приклад RPS (середнє / пік) Допустима затримка за ключем отримати замовлення за номером список останні 20 замовлень користувача, новіші спершу … … … … Окремо позначте великі файли (фото, відео, документи): їхнє місце — в об’єктному сховищі, а не в БД.
2. Типи баз даних
Для кожної сутності оберіть тип сховища і поясніть вибір через запити з етапу 1, а не через популярність.
| Тип | Коли пасує | Приклади |
|---|---|---|
| Реляційна (SQL) | транзакції, зв’язки між сутностями, складні запити, стабільна схема | PostgreSQL, MySQL |
| Документна | записи з різним набором атрибутів, читання документа цілком | MongoDB |
| Key-value | читання й запис за ключем з мінімальною затримкою | Redis, DynamoDB |
| Широкостовпцева | дуже багато записів, читання за ключем і діапазоном (наприклад, за часом) | Cassandra, ScyllaDB |
| Пошукова | повнотекстовий пошук, фільтри, ранжування | Elasticsearch, OpenSearch |
| Графова | запити зі зв’язків: друзі друзів, рекомендації | Neo4j |
| Часових рядів | метрики й події з часовою міткою, агрегація за періодами | TimescaleDB, InfluxDB |
| Об’єктне сховище | великі файли | Amazon S3 |
Для кожної сутності також визначте:
- Чи потрібні транзакції. Наприклад, списання грошей і резервування товару — так, лічильник переглядів — ні.
- Що важливіше під час збою мережі — консистентність чи доступність. Вибір має збігатися з тим, що ви зробили в Завданні №1.
Приклади таких рішень: онлайн-магазин (MongoDB для каталогу, MySQL для замовлень, Cassandra для архіву, S3 для зображень) і платформа ШІ-оцінювання (одна таблиця DynamoDB з TTL і умовними записами, щоб оцінку не надіслали двічі).
3. Реплікація і масштабування
🔮 Спершу вгадайте: скільки машин БД знадобиться вашій системі? Запишіть число, а наприкінці порівняйте з розрахунком.
Розрахуйте кількість машин для кожної БД окремо за трьома обмеженнями і візьміть найбільше значення:
Обмеження Формула Обсяг обсяг за 5 років з реплікацією / 50 ТБ Записи пікові записи / 1k RPS Читання пікові читання після кешу / 10k RPS Опишіть реплікацію. Скільки реплік і навіщо: доступність, резервні копії, розподіл читань. Якщо читання йдуть із реплік, поясніть, що станеться, коли репліка відстає від лідера і показує застарілі дані.
Якщо даних чи записів забагато для однієї машини, спроєктуйте шардування:
- ключ шардування (ідентифікатор користувача, хеш ключа, діапазон дат) і чому саме він;
- чи не з’являться «гарячі» шарди, куди потрапить непропорційно багато запитів;
- які запити стануть дорогими: об’єднання даних з різних шардів, запити «по всіх користувачах».
Якщо все вміщається на одну машину, шардування не робіть: зазначте, за якого зростання навантаження воно знадобиться.
4. Балансування навантаження
- Покажіть, де стоять балансувальники: перед сервісами, між репліками читання.
- Оберіть алгоритм (round robin, least connections, consistent hashing) і поясніть вибір. Consistent hashing, наприклад, пасує кешу й шардам: коли додається вузол, переїжджає лише невелика частина ключів.
- Опишіть перевірки стану (health checks): як балансувальник дізнається, що вузол недоступний, і що відбувається із запитами до нього.
- Записи — лише на лідера. Поясніть, що станеться, якщо лідер відмовить.
5. Кеш
- Що кешуємо і де: CDN для статики й файлів, кеш застосунку (Redis) для гарячих даних.
- Стратегія. Оберіть одну і поясніть:
- cache-aside — застосунок спершу читає кеш, а при промаху читає БД і кладе результат у кеш;
- write-through — запис іде одночасно в БД і в кеш.
- Інвалідація. Скільки живе запис у кеші (TTL) і коли його скидають примусово. Скільки часу користувач може бачити застарілі дані і чи це прийнятно для цієї сутності. Приклад свідомого компромісу — кеш Moodle на хвилину в платформі ШІ-оцінювання.
- Розрахунок:
- обсяг кешу — яку частку даних кешуємо і чому (наприклад, 20% найпопулярніших);
- очікувана частка влучань у кеш;
- навантаження на БД: читання × (1 − частка влучань).
- Що не кешуємо: дані, де застарілість неприпустима (залишки товару, баланс рахунку), і чому.
6. Схема та висновки
- Намалюйте схему: сервіси → балансувальники → кеш → БД (лідер і репліки, шарди) → об’єктне сховище.
- Що стане першим вузьким місцем, якщо навантаження зросте вдесятеро? Що ви зробите тоді?
- Наскільки розрахунок кількості машин відрізнився від вашої оцінки з етапу 3?
Що здати
- Звіт з усіма етапами: таблиці даних і запитів, вибір БД з обґрунтуванням, розрахунок машин, реплікація й шардування, балансування, кеш, схема й висновки.
- Коротку презентацію для обговорення на занятті. Порівнюватимемо, які БД обрали різні команди для схожих даних і чому.
Перед здачею перевірте
Матеріали для підготовки
- Слайди лекції «Збір вимог та оцінка навантаження»
- Розбір практики: онлайн-магазин і платформа ШІ-оцінювання робіт
- The System Design Primer: бази даних, SQL чи NoSQL, кеш, балансувальник навантаження
- Designing Data-Intensive Applications (Martin Kleppmann) — розділи про реплікацію та шардування
- System Design Interview (Alex Xu) — розділ «Scale From Zero To Millions Of Users»
- Textbook for System Design Interviews