Системний словник проектування: 40 термінів, які повинен знати кожен старший інженер
Теорема CAP, CQRS, пошук подій, автоматичний перемикач, saga — 40 термінів проектування систем, які ви повинні знати, щоб впевнено обговорювати розподілені системи в інтерв’ ю і оглядах архітектури.
Інтерв’ю з системним дизайном і обговорення архітектури мають спільну мову. Знання термінів точно - а не просто нечітко - це те, що відрізняє молодших відповідей від старших відповідей. Ці 40 термінів містять словниковий запас, який вам потрібен для обговорення розподілених систем, баз даних, надійності і розгортання з впевненістю.
Основи розподіленої системи
** Теорема CAP ** — Ви можете гарантувати лише дві з трьох властивостей одночасно: * Послідовність * (кожне читання отримує останній запис), * Доступність * (кожний запит отримує відповідь), * Дозволеність розділів * (система продовжує роботу, незважаючи на мережеві розділи). На практиці, розділи відбуваються, тому вибирайте між C і A.
** Моделі послідовності ** — спектр від * сильної послідовності * (зчитування завжди бачить останній запис) до * можливої послідовності * (зчитування з часом бачить останній запис). Проміжні моделі включають читати-ваші-писи, монотонні читання, і причинна послідовність.
** Послідовність можливих змін** — гарантія того, що, якщо не буде нових оновлень, всі репліки будуть збігатися до одного значення. Використовується в багатьох великих розподілених системах, де строга послідовність є занадто дорогою.
** Лінійність ** — Найсильніша модель послідовності: операції відбуваються атомарно і в порядку реального часу, в якому вони були видані. Фраза: “Лінієризована система поводиться так, ніби існує лише одна копія даних.”
** Шардинг ** — розділення даних на декілька вузлів, щоб кожен вузол містив лише підмножину. Зменшує навантаження на вузол. Фраза: “Ми розділяємо за ідентифікатором користувача — кожен шард обробляє одну восьму частину бази користувачів.”
** Реплікація ** — копіювання даних на декілька вузлів для збереження стійкості до помилок і можливості масштабування читання. Типи: лідер-наслідувач (основна репліка) і мульти-лідер (мульти-основна).
** Репліка для читання ** — копія бази даних, яка приймає лише читання, перевантажуючи трафік читання з головної бази даних. Фраза: “Запити аналітики надходять до репліки читання, тому вони не впливають на затримку запису на первинному.”
** Журнал передзапису (WAL) ** — Механізм тривалого зберігання: перед застосуванням зміни база даних записує її до журналу, який можна лише додати. Якщо система зламалася, WAL дозволяє відновлення.
Координація та консенсус
** Консенсус ** — Згода між розподіленими вузлами щодо одного значення (наприклад, хто є поточним лідером). Алгоритми: Raft, Paxos. Фраза: “Raft використовується для консенсусу — більшість вузлів повинна погодитися перед тим, як значення буде зафіксовано.”
** Вибори лідерів ** — процес, за допомогою якого розподілені вузли погоджуються щодо того, який вузол є поточним лідером, відповідальним за координацію записів. Поширений у базах даних (первинний вибір), чергах і службах координації.
** Розподілений блокування ** — блокування, яке діє на декількох вузлах, щоб запобігти одночасним змінам спільного ресурсу. Складніше, ніж локальний mutex, оскільки помилки мережі можуть призвести до зникнення тримача блокування.
** Двофазний затвердження (2PC) ** — Протокол для розподілених транзакцій: координатор просить всіх учасників * підготувати *, а потім каже їм * затвердити * або * скасувати *. Забезпечує атомарність, але блокує, якщо координатор завершить роботу.
** Ідемпотентність ** — Операція є ідемпотентною, якщо її застосування декілька разів дає такий самий результат, як і її застосування один раз. Критично важливо для безпечних повторних спроб. Фраза: “Використовувати ключ idempotency в API платежу, щоб повторні спроби не призвели до подвійного стягнення.”
** Доставка однієї і тієї ж адреси** — гарантія того, що повідомлення буде доставлено і оброблено однієї і тієї ж адреси, а не нуль разів (найчастіше один раз) або більше одного разу (принаймні один раз). Дуже важко досягти цього в розподілених системах.
Пам’ятки архітектури та побуту
** CQRS (Command Query Responsibility Segregation) ** — Відділення моделі запису (commands) від моделі читання (queries). Сторони запису і читання можуть використовувати різні бази даних, оптимізовані для відповідних навантажень.
** Походження подій ** — зберігання стану як послідовності незмінних подій, а не поточного значення. Поточний стан визначається за допомогою повторення подій. Фраза: “З використанням пошуку подій, ви можете переглянути історію, щоб побачити, яким був баланс рахунку в будь- який момент часу.”
** Saga ** — шаблон для керування розподіленими транзакціями як послідовністю локальних транзакцій, кожна з яких публікує подію або повідомлення, яке запускає наступний крок. Неуспіхи викликають компенсуючі транзакції.
** Черга повідомлень ** — тривалий буфер між виробниками і споживачами, який відокремлює їх за часом і пропускною здатністю. Приклади: Kafka, RabbitMQ, SQS. Фраза: “Служба замовлення публікує в чергу; служба виконання споживає у власному темпі.”
** Backpressure ** — Сигнал від повільного споживача до швидкого виробника, щоб сповільнити. Захищає від перевантаження споживача.
** Перегородка ** — Ізолювання компонентів, щоб пошкодження одного з них не переходило на інші, подібно до водонепроникних відсіків на кораблі. Фраза: “Ми застосували шаблон перегородки — платіжна служба має свій власний пул потоків, тому вона не може голодувати службу оплати.”
Надійність і управління рухом
** Circuit breaker ** — шаблон, який припиняє виклик служби, що зазнала невдачі, після досягнення певного порогу помилок, надаючи їй час на відновлення. Стани: * закрито * (нормальний), * відкрито * (блокування викликів), * напіввідкрито * (тестування відновлення). Фраза: “Відключник зарядився — ми повертаємо кешовані дані доки потік не відновиться.”
** Обмеження частоти ** — обмеження кількості запитів, які клієнт може зробити за певний проміжок часу. Алгоритми: контейнер для символів, контейнер для непроникних даних, вікно з пересувними елементами. Фраза: “API обмежений швидкістю до 1000 запитів на хвилину на ключ API.”
** Балансування навантаження ** — розподіл вхідного трафіку між декількома серверами. Алгоритми: круговий облік, найменше з’ єднань, послідовне гешування.
** CDN (Content Delivery Network) ** — географічно розподілена мережа серверів, яка кешує статичний вміст поруч з користувачами, зменшуючи затримку і навантаження на сервер початкового коду.
** Шляхи кешування ** — декілька рівнів кешування: кеш переглядача, краєвий кеш CDN, кеш рівня програми (Redis, Memcached), кеш запиту бази даних.
** API gateway ** — єдина точка входу для зовнішніх клієнтів, що обробляє маршрутизацію, розпізнавання, обмеження швидкості і переклад протоколів.
** Service mesh ** — шар інфраструктури для обміну даними між службами: mTLS, повторні спроби, розрив схеми, спостережність. Приклади: Istio, Linkerd.
** Пошук служб ** — Механізм, за допомогою якого служби знаходять розташування мережі один одного. Приклади: Consul, Kubernetes DNS, AWS Cloud Map.
** Перевірка стану ** — кінцева точка або зонд, який вказує, чи є екземпляр служби у належному стані і готовий обслуговувати трафік.
Розгортання та база даних
** Розгортання синьо- зеленого кольору ** — Два середовища; перемикання трафіку між ними для випусків без перерв.
** Canary deployment ** — Поступово переносити трафік до нової версії; повертати назад, якщо показники погіршуються.
** Прапорець можливості ** — Перемикач часу виконання для увімкнення або вимкнення можливостей без розгортання коду.
** Розділення бази даних на розділи ** — Розділення таблиці на менші частини (розділи), які зберігаються окремо. Покращує швидкодію запиту на великі таблиці.
** Об’ єднання з’ єднань ** — Повторне використання з’ єднань з базою даних замість відкриття нового з’ єднання за запитом. Зменшує витрати на з’ єднання.
** Індекс ** — структура даних, яка прискорює завдання читання за рахунок витрат на запис і зберігання.
** Планувальник запитів ** — компонент бази даних, який визначає оптимальний план виконання запиту.
** Оптимістичне блокування ** — Припускає відсутність конфлікту; перевіряє під час збереження. Ефективний для низькоконфліктних ситуацій.
** Песимістичне блокування ** — Блокувати ресурс під час читання, запобігаючи одночасним змінам.
** Race condition ** — Вада, результат якої залежить від часу одночасних дій.
** Заблоковано ** — дві або більше транзакцій, кожна з яких чекає на блокування іншої, що призведе до затримки.
** Вправа: ** Під час наступного обговорення або інтерв’ ю щодо проектування системи, свідомо використовуйте принаймні десять з цих термінів у їх правильному контексті. Запис ваших відповідей на імітацію питання з проектування системи і повторення відповіді є одним з найефективніших способів виявлення прогалин у вашому технічному словнику.
Використання мови: мова для міжнародних переговорів
Багато з вас, хто читає це, мають різне походження, і це фантастично. Це приносить багатство перспектив технічних обговорень. Однак, навігація нюансами професійної англійської мови - особливо в системному дизайні - може бути викликом, коли ваша перша мова не є англійською. Словниковий запас тут точний, часто шаруватий з тонкими наслідками, і часто покладається на встановлені шаблони спілкування. Не хвилюйтеся про те, щоб негайно зрозуміти кожен термін; це подорож безперервного навчання. Цей розділ зосереджений на тому, як ці терміни перекладаються в повсякденні сценарії на робочому місці, пропонуючи контекст для тих, хто активно прагне поліпшити свою англійську мову в технічному середовищі.
Однією з поширених перешкод є розуміння різниці між «вплином» і «компромісом» при обговоренні вибору дизайну. Просто сказати: «Ця зміна має великий вплив», недостатньо в перегляді коду. Старший інженер може відповісти: «Давайте кількісно оцінимо цей вплив. Чого ми жертвуємо, щоб досягти цього? Чи існують альтернативні підходи, які зменшують потенційні негативні наслідки – можливо, вводячи простіше рішення спочатку і розвиваючи його пізніше?” Метою є перехід від суб’єктивних почуттів до демонстраційних доказів розуміння системних наслідків. Аналогічно, при описі запропонованої зміни в запиті на витяг, використання фраз на кшталт «оптимізація для затримки» проти «зменшення складності операцій» може радикально змінити те, як ваша пропозиція буде прийнята. Це стосується вибору найточнішої мови, щоб передати те, на що ви націлені.
Іншою областю, де часто виникає плутанина, є поняття « масштабованість » і « продуктивність ». Хоча вони здаються пов’ язаними, вони є різними поняттями. « Масштабованість » стосується здатності системи обробляти зростаюче навантаження — більше користувачів, більше даних тощо — без значного зниження продуктивності. « Продуктивність », з іншого боку, стосується того, наскільки * швидко * система відповідає на окремі запити. Ви можете ідеально масштабувати систему і все одно мати погану продуктивність, якщо сама архітектура не оптимізована для швидкості. Фраза на кшталт « Нам потрібно поліпшити затримку 95-го процентиля » повідомляє про чітку технічну мету, яка набагато більш реалізована, ніж просто сказати « система повільна ». Сфокусуйтеся на тому, щоб бути конкретним щодо того, що потрібно поліпшити і чому.
І нарешті, пам’ ятайте, що активне слухання і запитання прояснюючих питань є вашими найкращими інструментами. Не бійтеся запитати: « Чи можете ви розібратися, що ви маєте на увазі під « зменшенням технічного боргу » у цьому контексті? » або « Чи можете ви надати мені конкретний приклад того, як ця зміна впливає на загальну архітектуру системи? » Показувати бажання вивчити і зрозуміти є набагато ціннішим, ніж негайно намагатися правильно використовувати складну термінологію. Це про будівництво спільного розуміння, а не про демонстрацію майстерності.
Ось приклад використання kubectl для опису розгортання:
kubectl describe deployment my-app --namespace production
За допомогою цієї команди можна отримати докладні відомості щодо розгортання, зокрема його реплік, запитів/ обмежень ресурсів, а також будь- яких спостережених подій — всі ці дані є важливими для обговорення швидкодії або масштабування.