Мікросервіси без дублювання даних


20

Мені важко уникнути дублювання даних або спільної бази даних навіть для найпростішого дизайну мікросервісів, через що я думаю, що мені чогось не вистачає. Ось основний приклад проблеми, з якою я стикаюся. Якщо припустити, що хтось використовує веб-додаток для управління запасами, їм знадобляться дві послуги; один для інвентарю, що керує товарами та кількістю на складі, і послуга користувачів, яка керує даними користувачів. Якщо ми хочемо перевірити, хто зберігав базу даних, ми могли б додати ідентифікатор користувачів до бази даних для служби інвентаризації як останній запас за вартістю.

Використовуючи додаток, ми можемо захотіти побачити всі предмети, які закінчуються, і список тих, хто їх накопичив минулого разу, щоб ми могли попросити їх відновити його ще раз. Використовуючи описану вище архітектуру, до служби інвентаризації буде подано запит на отримання реквізитів усіх предметів, де кількість менше 5. Це поверне список, включаючи ідентифікатори користувачів. Тоді до служби користувачів буде зроблено окремий запит, щоб отримати ім’я користувача та контактні дані для списку ідентифікаторів користувачів, отриманих від служби інвентаризації.

Це здається жахливо неефективним, і це не потребує набагато більше служб, перш ніж ми робимо кілька запитів до різних API API-служб, які, в свою чергу, роблять кілька запитів до бази даних. Альтернативою є копіювання реквізитів користувачів у даних інвентаризації. Коли користувач змінює свої контактні дані, тоді нам потрібно буде повторити зміни через усі інші служби. Але це, схоже, не відповідає обмеженій контекстній ідеї мікросервісів. Ми також могли б використовувати єдину базу даних і ділитися цим між різними службами та мати всі проблеми інтеграційної бази даних .

Який правильний / найкращий спосіб здійснити це?


5
Ласкаво просимо до парадоксу мікропослуг. Те, що могло б зробити простішими речі, насправді може зробити речі складнішими.
Роберт Харві

"Правильний" спосіб такий самий, як це було завжди: придумайте спосіб виконання дій, який найкраще відповідає вашим конкретним цілям.
Роберт Харві

1
@RobertHarvey Це завжди так, але я намагаюся зрозуміти підручник мікропослугами. Як тільки я зрозумію, як це має працювати в ідеальному світі, я з радістю зміню його, щоб відповідати моєму використанню.
Жерайн Андерсон

1
Але ви поставите своє питання щодо ефективності, що є нефункціональною вимогою до програмного забезпечення. Спосіб вирішення проблеми ефективності - це запитання безпосередньо в базі даних.
Роберт Харві

1
Я збирався написати питання саме так, як ваше. Я все ще не бачу переваг в MSA для досить простих веб-додатків. Я думаю, що в багатьох випадках модульність можна було б досягти, не роблячи речі настільки складними.
Glasnhost

Відповіді:


10

Я повністю пропустив те, де від вас вимагають копіювати.

Основним принципом мікропослуг є те, щоб служба була єдиною владою. Це означає, що управління запасами та користувачем може бути абсолютно окремим. Я б розробив управління користувачем таким чином, щоб воно навіть не знало, що існує система інвентаризації.

Але я б розробив систему інвентаризації так, щоб вона ніколи не зберігала нічого про користувачів, окрім ідентифікатора користувача. Це вирішує вашу проблему із поширенням змін інформації про користувача.

Що стосується речей, які потребують як інформації про інвентаризацію, так і інформацію про користувачів, такі як журнали, аудити та роздруківки, вони не оновлюються як зміни інформації. Вони є записом того, що було. Знову ж таки, ви не поширюєте зміни.

Тому в будь-якому випадку, коли ви хочете отримати останню інформацію про користувача, ви запитаєте інформацію про службу користувача.


@Geraint: Чи можете ви бути більш конкретними щодо дублювання, яке відбувається у вашій системі?
Роберт Харві

1
Спасибі. Дублювання стосувалося копіювання контактних даних користувачів до служби інвентаризації, але ви звернулися до цього (тобто це не потрібно). Здається, протилежно інтуїтивно переходити з єдиної реляційної бази даних, де я міг би отримати дані інвентаризації та дані користувачів з приєднанням до здійснення двох чітких викликів API, де другий не може розпочатися, поки перший не поверне результати. Але я думаю, що це частина оцінки того, чи використовую я мікросервіси чи щось інше.
Жерайн Андерсон

Це той самий трюк, який використовував би БД, якби він керував обома. Ви не копіюєте інформацію про користувача у таблицю інвентаризації. Ви даєте йому закордонний ключ. Ідентифікатор користувача виконує однакову роботу в усіх службах. Просто зробіть його унікальним.
candied_orange

It seems counter-intuitive to move from a single relational database where I could get the inventory data and the user data with a joinМайте на увазі, що "в ідеалі" є один магазин на послугу (або більше!). Отже, немає нічого подібного, як "приєднатися" між "межами". Причина проста, DB генерує зв'язок між службами. На відміну від пропозиції @CandiedOrange, я думаю, що ми можемо копіювати мінімум даних з однієї служби в іншу. Я маю на увазі дані, які навряд чи зміняться. Якщо цей поєдинок підвищить ефективність та ефективність (і потрібні обидва), "плюси", ймовірно,
компенсують

@GeraintAnderson Я маю на увазі, якщо вам потрібна ефективність (яка за визначенням є нефункціональною вимогою), є способи це зробити. Тобто сторінки запитів даних із Служби інвентаризації (наприклад, 10 елементів), візьміть кожну сторінку та використовуйте її для запиту даних у Службі користувачів і зберіть в кінці. Таким чином ви зберігаєте свої межі, використовуючи паралелізм незалежних служб. Навіть тоді не турбуйтеся, поки ви не визначите це як справжнє вузьке місце програми, яке потрібно вирішити - чекати додаткових 1/2 секунди на 1-секундну роботу за ніч нікого не має значення.
Delioth

11

Мені важко уникнути дублювання даних….

Згідно з електронною книжкою Microsoft з архітектури мікросервісів , у дублюванні даних немає нічого поганого. В основному, дублювання даних збільшує розв'язку між службами і, отже, посилює їх роль як єдиного органу. Відповідний уривок:

І нарешті (і саме тут виникає більшість проблем при створенні мікросервісів), якщо вашій початковій мікросервісі потрібні дані, які спочатку належать іншим мікросервісам, не покладайтеся на отримання синхронних запитів на ці дані. Натомість копіюйте або поширюйте ці дані (лише необхідні атрибути) у базу даних початкової служби, використовуючи можливу послідовність (як правило, використовуючи події інтеграції ...


1
Я повністю не згоден. Це ускладнює утримання. Це дозволяє вам здійснювати транзакції серед мікросервісів, коли щось потрібно додавати, оновлювати чи видаляти. Якщо ви хочете запобігти одній точці помилки, ви можете використовувати запит або будь-який інший тип кешування.
Алан Сереб

1
@AlanSereb Це важче підтримувати, але справа в тому, що іноді у тебе немає іншого вибору. Наприклад, що робити, якщо вам потрібно зробити ФК між об'єктами, що живуть у двох базах даних? Єдиний спосіб забезпечити послідовність під час запитів у локальній БД - це реплікація даних. Погляньте на сторінку: stackoverflow.com/a/4452586/2255491
Девід Д.

Я згоден. Ще один чудовий підхід - пройти маршрут пошуку подій. І чи всі мутації будуть виконані через конвеєр подій
Алан Сереб

4

до служби інвентаризації буде подано запит на отримання реквізитів усіх предметів, де кількість менше 5. Це поверне список, включаючи ідентифікатори користувача. Тоді до служби користувачів буде зроблено окремий запит, щоб отримати ім’я користувача та контактні дані для списку ідентифікаторів користувачів, отриманих від служби інвентаризації.

Дійсно, так.

Зрозуміло, що в моноліті ви можете мати модель інвентаризації, за якою ви запитуєте відповідні елементи, подайте їх у користувальницьку модель і отримуйте ті самі дані.

Або ви можете взяти його далі, якщо ви маєте їх в одній реляційній базі даних і напишіть SQL, що і база даних візьме таблицю інвентаризації та користувальницьку таблицю, це робить деяку магію, і ви отримаєте дані, які ви шукаєте.

Незалежно від того, як ви це зробите, десь буде код, який по суті отримує список ідентифікаторів користувачів із системи інвентаризації, подає їх у систему користувача та складає список даних.

Питання, на яке вам потрібно відповісти, стосується продуктивності та технічного обслуговування та інших "м'яких" якостей.

Основна перевага мікросервісів - масштабування. Якщо у вас на одній машині десять тисяч користувачів, і це трохи мляво, ви можете додати іншу машину, і система стає вдвічі швидшою. Додайте ще вісім, і це в десять разів швидше. (Лінійне масштабування, мабуть, оптимістично, але це ідеал і не це необгрунтований на сподівання.)

І це за послугу . Якщо система інвентаризації є вузьким місцем, вона використовується для більш ніж звітів про користувачів, ви можете додати більше машин до цієї послуги . Машини також можуть бути спеціалізованими; цьому сервісу потрібно багато пам’яті, цей сервіс робить важкі розрахунки та потребує більшої кількості процесорів.

Якщо вам не потрібно масштабування, є ще одна перевага мікросервісів: вони модульні . Звичайно, монолітні програми також можуть бути модульними, і у вас є нормалізована база даних і ... але на практиці стіни між модулями є як скляні стіни в кращому випадку, а лінії на піску в гіршому. Мікросервіси розділені твердою сталлю.

Якщо ваша система користувачів буквально загоряється, це звичайно не вплине на вашу інвентарну систему. Ви не зможете надрукувати чудові звіти про те, хто чим запас, але клієнти зможуть безпечно розміщувати замовлення, знаючи, що там є товари, що запасаються.

І ви не дублюєте дані в мікросервісах , більше ніж у реляційній базі даних (*). У реляційній базі даних ви можете зробити з'єднання , а еквівалент - об'єднати списки в коді, як описано.

Ви також можете додати перегляд , еквівалент - додати нову послугу, яка робить злиття для вас; це призвело б до трьох запитів; один до нової служби, а потім ця послуга робить оригінальні дві. Реляційні бази даних мають вигадливі речі, що оптимізують представлення даних, які мають бути впроваджені на рівні сервісу. Ви не отримуєте це "безкоштовно".

Кешування відрізняється від дублювання даних тим, що якщо два значення не відповідають, ви знаєте, яке з них неправильно. Він часто використовується в мікросервісах для підвищення доступності за рахунок послідовності (теорема CAP). Оскільки реляційні бази даних повністю доступні для отримання м'яса на вівтарі консистенції, то в них рідше. Я б сказав, що нічого не властивого мікросервісам, що робить кешування простішим, але на практиці кешування є першочерговою проблемою, а це робить полегшення кешування у мікросервісах .

(*) Якщо є сенс дублювати дані в річку мікросервісу, то, мабуть, це має сенс у еквівалентній реляційній базі даних.


3
Мені дуже сподобалася ваша відповідь, поки частина "не дублювати дані в мікросервісах". Я думаю, що є випадки, коли дублювання даних - це правильний підхід. Це покращує відмовостійкість і самостійність. Якщо служба користувачів знизилася, служба інвентаризації все ще може відображати список низьких запасів із тим, хто їх накопичив останнім часом.
Пітер Помпеї

1
@peterpompeii Я б назвав це кешування, а не дублювання даних. Дублювання даних - це коли у вас є два місця для оновлення для однієї дати, кешування, коли є одне місце, і автоматичне поширення в інші місця. Також я сказав більше, ніж реляційний. Якщо в реляційній базі даних є сенс дублювати дані, в мікросервісі є сенс. Я думаю, що ми погоджуємось, і ця частина може бути зрозумілішою, але я маю лише зараз телефон, тому зараз текст не оновлюється.
Одалрік

@PeterPompeii Сподіваємось, що доданий розділ про кешування вирішує деякі ваші проблеми.
Одалрік

1
@Odalrick, що ви описали, звучить як реплікація даних. Реплікація та кешування - це обидві форми дублювання даних. Реплікація - це коли копія гарантовано завжди має всі необхідні дані. Кешування - за запитом. Тренування може мати промах. Кешування доступності не має такого сенсу, як кешування продуктивності. TL; DR, якщо ви зберігаєте повну копію чогось із достатньою послідовністю, гарантує, що вам ніколи не потрібно перевіряти пропуски, то це не кеш.
Брендон

1
@Brandon Ще одна відмінність між реплікацією та кешуванням полягає в тому, як ви знаєте, які дані неправильні, коли є різниця. Реплікація визначає деякі правила щодо об’єднання даних. Кешування з іншого боку - це завжди : кеш неправильний.
Одалрік,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.