Пошук уроків, статей та іншого контенту
Розглянемо вузли, мережеві взаємодії, реплікацію, масштабування та джерела складності розподілених систем.
Розподілена система — це система, компоненти якої працюють на кількох незалежних комп’ютерах і взаємодіють через мережу.
Для користувача така система може виглядати як один застосунок. Насправді запит може пройти через кілька компонентів:
Клієнт → сервер застосунку → база даних
↘
сервіс повідомленьКожен компонент може працювати на окремому сервері або в окремому контейнері.
Приклади розподілених систем:
вебзастосунок із кількома серверами;
база даних із репліками;
платформа онлайн-магазину;
система доставки повідомлень;
хмарний сервіс.
Головна відмінність від програми на одному комп’ютері — наявність мережі та незалежних компонентів, які можуть працювати або виходити з ладу окремо.
Вузол — це окремий учасник системи, який виконує роботу або зберігає дані.
Вузлом може бути:
сервер застосунку;
база даних;
кеш;
брокер повідомлень;
окремий сервіс;
фізичний або віртуальний комп’ютер.
Наприклад, замість одного сервера застосунку можна запустити три:
┌─ Сервер 1
Клієнти ──────┼─ Сервер 2
└─ Сервер 3Ці сервери можуть обробляти запити паралельно.
Вузли взаємодіють через мережу. Один вузол надсилає повідомлення, а інший його обробляє та повертає відповідь.
Мережевий запит не є миттєвим. Він може:
займати різний час;
бути доставленим із затримкою;
не дійти до отримувача;
бути повторений через повторну спробу;
отримати відповідь після того, як клієнт уже припинив чекати.
Тому розподілена система не може поводитися так, ніби всі компоненти працюють у спільній пам’яті.
Сховище відповідає за збереження даних. У простій системі це може бути одна база даних. У більшій системі дані можуть бути розподілені між кількома вузлами.
Сховище може використовуватися для:
збереження профілів користувачів;
зберігання замовлень;
зберігання сесій;
журналювання подій;
обміну даними між сервісами.
Клієнт — це компонент, який ініціює запит. Ним може бути:
браузер;
мобільний застосунок;
інший сервер;
фонове завдання.
Клієнт не обов’язково знає, на якому саме вузлі буде оброблено його запит.
Взаємодія між вузлами зазвичай складається з таких кроків:
Відправник формує повідомлення.
Повідомлення передається мережею.
Отримувач приймає повідомлення.
Отримувач виконує операцію.
Отримувач повертає результат.
Наприклад, сервер замовлень може звернутися до сервісу оплати:
Сервіс замовлень ── запит на оплату ──> Сервіс оплати
Сервіс замовлень <─ результат операції ─ Сервіс оплатиУ кожній такій взаємодії потрібно враховувати:
час очікування;
помилку мережі;
недоступність сервісу;
повторну відправку запиту;
отримання відповіді лише частиною системи.
Якщо вузол не відповідає нескінченно довго, клієнт або інший сервіс використовує тайм-аут.
Наприклад:
Якщо відповідь від сервісу оплати не надійшла за 5 секунд, вважати операцію такою, що не завершилася вчасно.
Тайм-аут не завжди означає, що операція не виконалася. Сервер міг провести оплату, але відповідь загубилася в мережі. Через це повторення запиту може бути небезпечним.
Коли запит не отримав відповіді, система може повторити його. Це допомагає пережити тимчасові проблеми, але створює нові ризики:
одна операція може виконатися кілька разів;
навантаження на несправний сервіс може збільшитися;
користувач може отримати різні результати.
Тому повтори потрібно використовувати обережно. Для операцій на кшталт створення платежу важливо мати спосіб розпізнати повторний запит.
Реплікація — це зберігання однакових або узгоджених даних на кількох вузлах.
Наприклад, дані можуть зберігатися на трьох серверах:
┌─ Репліка 1
Основні дані ────┼─ Репліка 2
└─ Репліка 3Реплікація допомагає:
продовжити роботу після відмови одного вузла;
розподілити запити на читання;
зменшити навантаження на один сервер;
зберігати додаткові копії даних.
Під час синхронної реплікації операція вважається завершеною після підтвердження від кількох реплік.
Перевага:
менша ймовірність втратити підтверджені дані.
Недоліки:
запис може бути повільнішим;
недоступність репліки може заблокувати операцію.
Під час асинхронної реплікації основний вузол може підтвердити запис раніше, а репліки оновляться пізніше.
Переваги:
швидший запис;
тимчасова недоступність репліки не обов’язково зупиняє основний вузол.
Недолік:
деякий час репліки можуть містити застарілі дані.
Це називають затримкою реплікації.
Користувач записав дані через вузол A, а потім одразу прочитав їх через вузол B.
Можлива ситуація:
Запис через A: "статус = оплачено"
Читання через B: "статус = очікує оплату"Це не обов’язково означає помилку. Вузол B може ще не отримати оновлення від A.
Ось спрощена runnable-модель такої поведінки на JavaScript:
class Replica {
constructor(name) {
this.name = name;
this.data = new Map();
}
write(key, value) {
this.data.set(key, value);
}
read(key) {
return this.data.get(key);
}
receive(message) {
this.write(message.key, message.value);
}
}
const primary = new Replica("primary");
const secondary = new Replica("secondary");
const messages = [];
function writeToPrimary(key, value) {
primary.write(key, value);
// Імітуємо асинхронну доставку оновлення репліці
messages.push({
target: secondary,
key,
value
});
}
function deliverMessages() {
while (messages.length > 0) {
const message = messages.shift();
message.target.receive(message);
}
}
writeToPrimary("order:42", "paid");
console.log("Основний вузол:", primary.read("order:42"));
console.log("Репліка до синхронізації:", secondary.read("order:42"));
deliverMessages();
console.log("Репліка після синхронізації:", secondary.read("order:42"));Результат буде приблизно таким:
Основний вузол: paid
Репліка до синхронізації: undefined
Репліка після синхронізації: paidЦей приклад спрощений: у реальній системі потрібно вирішувати питання порядку повідомлень, конфліктів і повторної доставки.
Масштабування — це збільшення здатності системи обробляти навантаження.
Вертикальне масштабування означає збільшення ресурсів одного вузла:
більше оперативної пам’яті;
потужніший процесор;
швидший диск;
більша пропускна здатність мережі.
Перевага — простіша архітектура. Недолік — один вузол усе ще залишається обмеженням і потенційною точкою відмови.
Горизонтальне масштабування означає додавання нових вузлів.
┌─ Сервер 1
Клієнти ──────┼─ Сервер 2
└─ Сервер 3Переваги:
запити можна розподілити між вузлами;
відмова одного вузла не обов’язково зупиняє систему;
потужність можна збільшувати поступово.
Але горизонтальне масштабування додає складності:
вузли потрібно координувати;
дані мають бути доступними там, де вони потрібні;
потрібно визначати, куди направляти запити;
необхідно стежити за станом вузлів.
Реплікація створює копії даних. Масштабування збільшує здатність системи обробляти навантаження.
Вони можуть використовуватися разом, але мають різні цілі:
реплікація допомагає з доступністю та читанням;
додаткові сервери застосунку допомагають обробляти більше запитів;
розподіл даних між вузлами допомагає працювати з більшим обсягом даних.
У монолітній програмі на одному комп’ютері відмова часто впливає на всю програму. У розподіленій системі може відмовити лише один компонент.
Наприклад:
сервер застосунку працює;
база даних тимчасово недоступна;
кеш працює, але містить старі дані;
один із серверів повільно відповідає.
Система має визначити, що робити в кожному випадку.
Час відповіді залежить не лише від коду, а й від:
відстані між вузлами;
завантаження мережі;
черги запитів;
стану сервера;
кількості послідовних взаємодій.
Якщо один користувацький запит потребує п’яти послідовних мережевих викликів, загальний час відповіді може суттєво зрости.
Якщо існує кілька копій даних, вони можуть тимчасово відрізнятися.
Потрібно визначити:
коли зміни мають стати видимими;
який вузол вважається джерелом істини;
що робити, якщо два вузли отримали різні зміни;
чи допустиме короткочасне читання старих даних.
Для одних даних застаріле значення допустиме. Наприклад, лічильник переглядів може оновитися із затримкою. Для інших даних це небезпечно, наприклад для залишку товару або стану платежу.
Повідомлення можуть прибути не в тому порядку, у якому були відправлені.
Наприклад:
1. Встановити статус "оплачено"
2. Встановити статус "скасовано"Якщо друге повідомлення прибуде раніше за перше, репліка може отримати неправильний результат без додаткового механізму впорядкування.
У системі з багатьма вузлами складніше зрозуміти, де виникла проблема. Для діагностики зазвичай потрібні:
журнали подій;
метрики;
ідентифікатори запитів;
інформація про час відповіді;
повідомлення про помилки.
На базовому рівні важливо запам’ятати: помилка може виникнути не лише в бізнес-логіці, а й під час передачі запиту між компонентами.
Під час аналізу системи корисно послідовно поставити такі запитання:
Які є вузли?
Які дані зберігає кожен вузол?
Як вузли взаємодіють?
Що станеться, якщо один вузол стане недоступним?
Чи можуть дані на різних вузлах тимчасово відрізнятися?
Як система обробляє повільні відповіді?
Як система масштабується при збільшенні навантаження?
Ці питання допомагають побачити не лише нормальний сценарій, а й поведінку системи під час затримок та відмов.
Мережа може бути повільною або недоступною. Кожен важливий мережевий виклик має мати зрозумілу поведінку у разі помилки.
За асинхронної реплікації нові дані можуть з’явитися на інших вузлах із затримкою.
Повторний запит може повторно виконати операцію. Особливо небезпечно автоматично повторювати операції, що створюють платежі, замовлення або інші побічні ефекти.
Кілька серверів не гарантують масштабування. Потрібно розуміти, як між ними розподілятимуться запити, дані та відповідальність.
Якщо один сервіс недоступний, уся система не обов’язково має повністю зупинятися. Потрібно заздалегідь визначити допустиму поведінку: повернути помилку, використати резервні дані або повторити операцію.
Розподілена система складається з незалежних вузлів, які взаємодіють через мережу.
Мережеві виклики мають затримки, можуть завершуватися помилкою або не отримувати відповіді.
Реплікація зберігає копії даних на кількох вузлах.
Синхронна реплікація зазвичай дає свіжіші дані, але може збільшувати час запису.
Асинхронна реплікація може бути швидшою, але допускає тимчасово застарілі копії.
Вертикальне масштабування збільшує ресурси одного вузла, а горизонтальне додає нові вузли.
Основні джерела складності — часткові відмови, затримки, неузгодженість даних, повтори та порядок повідомлень.
Під час проєктування важливо описувати не лише успішний сценарій, а й поведінку системи під час проблем.