Русский
Русский
English
Статистика
Реклама

Commit

Паттерн сага как способ обеспечения консистентности данных

18.09.2020 14:13:41 | Автор: admin
Всем привет. Уже сейчас в OTUS открывает набор в новую группу курса Highload Architect. В связи с этим я продолжаю серию своих публикаций, написанных специально для этого курса, а также приглашаю вас на свой бесплатный демо урок по теме: Индексы в MySQL: best practices и подводные камни. Записаться на вебинар можно тут.



Введение


Как известно, переход от монолита к микросервисной архитектуре вызывает ряд сложностей, связанных как с технической частью проекта, так и с человеческим фактором. Одной из самых сложных технических проблем вызывает обеспечение согласованности в распределенной системе.

В прошлый раз мы обсудили причины возникновения проблем с согласованностью в микросервисной архитектуре, оптимистичный подход в обеспечению согласованности и обеспечение согласованности с применением двухфазного коммита.

Паттерн Сага


Сага это механизм, обеспечивающий согласованность данных в микросервисной архитектуры без применения распределенных транзакций.

Для каждой системной команды, которой надо обновлять данные в нескольких сервисах, создается некоторая сага. Сага представляет из себя некоторый чек-лист, состоящий из последовательных локальных ACID-транзакций, каждая из которых обновляет данные в одном сервисе. Для обработки сбоев применяется компенсирующая транзакция. Такие транзакции выполняются в случае сбоя на всех сервисах, на которых локальные транзакции выполнились успешно.

Типов транзакций в саге несколько, целых четыре:

  • Компенсирующая отменяет изменение, сделанное локальной транзакцией.
  • Компенсируемая это транзакция, которую необходимо компенсировать (отменить) в случае, если последующие транзакции завершаются неудачей.
  • Поворотная транзакция, опеределяющая успешность всей саги. Если она выполняется успешно, то сага гарантированно дойдет до конца.
  • Повторяемая идет после поворотной и гарантированно завершается успехом.

Организовывать сагу можно с помощью хореографии или оркестрации.

В случае с хореографической саги выделенный оркестратор отсутствует. На примере сервиса заказов и пользователей она может выглядеть так: сервис заказов получает запрос и создает заказ в состоянии PENDING, а затем публикует событие Заказ создан. Обработчик событий в сервисе пользователей обрабатывает данное событие, пытается зарезервировать товар и публикует результат в виде события. Сервис заказов обрабывает данное событие, подтверждая или отменяя заказ в зависимости от прочитанного результата.

Сага с оркестрацией выглядит чуть более интересно. На примере указанных выше сервисов может получиться так: сервис заказов получает запрос, создает сагу, которая создает заказ в состоянии PENDING, а затем отправляет команду резервирования товара для сервиса пользователей. Сервис пользователей пытается зарезервировать товар и отправляет ответное сообщение с указанием результата. Сага одобряет или отменяет заказ.

Паттерн сага позволяет приложению поддерживать согласованность данных между нескольких сервисов без использования распределенных транзакций (двухфазных коммитов) и с избежанием проблем, обсужденных в предыдущей статье. Но с другой стороны, сильно осложняется модель программирования: например, разработчик для каждой транзакции должен писать компенсирующую транзакцию, которая отменяет изменения, сделанные внутри саги ранее.

Сага позволяет добиться ACD-модели (Atomicity + Consistency + Durability в терминах ACID), но одну букву мы потеряли. Недостаток буквы I приводит к известным проблемам недостатка изолированности. К ним относятся: потерянные обновления (lost updates) одна сага перезаписывает изменения, внесенные другой, не читая их при этом, грязное чтение (dirty reads) транзакция или сага читают незавершенные обновления другой саги, нечеткое/неповторяемое чтение (fuzzy/nonrepeatable reads) два разных этапа саги читают одни и те же данные, но получают разные результаты, потому что другая сага внесла изменения. Существует ряд паттернов, позволяющих пофиксить те или иные аномалии: семантическая блокировка, коммутативные обновления, пессимистическое представление, повторное чтение значения, файл изменений и по значению. Вопрос обеспечения изоляции остается открытым.

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

Заключение


Мы поговорили о способах организации саги с применением хореографии и оркестрации, а также о проблемах, которые влечет применения данного паттерна. Далее мы поговорим о способах исправления некоторых аномалий и транзакционной отправки сообщений в брокер сообщений.

Подробнее..

Проблематика распределенных транзакций в контексте микросервисной архитектуры

27.08.2020 10:09:54 | Автор: admin
Всем привет. Уже в сентябре OTUS открывает набор в новую группу курса Highload Architect. В связи с этим я продолжаю серию своих публикаций, написанных специально для этого курса, а также приглашаю вас на свой бесплатный вебинар, в рамках которого я подробно расскажу о программе курса и формате обучения в OTUS. Записаться на вебинар можно тут.



Введение


Как известно, переход от монолита к микросервисной архитектуре вызывает ряд сложностей, связанных как с технической частью проекта, так и с человеческим фактором. Одной из самых сложных технических проблем вызывает обеспечение согласованности в распределенной системе.

Согласованность


Достаточно тонким моментом является то, что согласованность в контексте распределенных систем отличается от согласованности в контексте баз данных. Далее под согласованностью мы будем понимать именно первое: незавершенная (ошибочная) операция не вносит никаких эффектов и не меняет данные, при конкурентном доступе к данным все операции рассматриваются как атомарные (нельзя увидеть промежуточный результат операции), если у данных имеется несколько копий (репликация), то последовательность применения операций на всех копиях одна и та же. То есть на самом деле мы хотим получить ACID транзакцию, но только распределенную.

Причина проблемы


Почему обеспечение согласованности затруднено именно в микросервисной архитектуре? Дело в том, что данный архитектурный стиль зачастую предполагает применение паттерна database per service. Позволю себе напомнить, что этот паттерн заключается в том, что у каждого микросервиса своя независимая база или базы (базы, потому что помимо первичного источника данных может использоваться, например, кеш). Такой подход позволяет с одной стороны не добавлять неявные связи по формату данных между микросервисами (микросервисы взаимодействуют только явно через API), с другой стороны по максимуму использовать такое преимущество микросервисной архитектуры как technology agnostic (мы можем выбирать подходящую под особую нагрузку на микросервис технологию хранения данных). Но при всем при этом мы потеряли гарантию согласованности данных. Посудите сами, монолит общался с одной большой базой, которая предоставляла возможности по обеспечению ACID транзакций. Теперь баз данных стало много, а вместо одной большой ACID транзакции у нас много небольших ACID транзакций. Нашей задачей будет объединение всех этих транзакций в одну распределенную.

Оптимистичная согласованность


Первое что может прийти в голову это концепция оптимистичной согласованности: мы совершаем столько транзакций сколько хотим на столько механизмов хранения сколько нужно. При этом мы ждем, что все будет хорошо, а если все плохо, то говорим, что все будет хорошо в итоге. Если все плохо в итоге, то говорим: Да, такое случается, но с крайне низкой вероятностью.

Если без шуток, то пренебрежение обеспечением согласованности в случае ее некритичности для бизнеса является хорошим решением, особенно если учесть то, каких усилий нам будет стоить ее обеспечение (в чем, как я надеюсь, вы убедитесь несколько позже).

Варианты обеспечения консистентности


Если для бизнеса все-таки согласованность является критичной, можно попытаться ее обеспечить несколькими способами. Если мы говорим о ситуации, когда данные обновляются одним сервисом (например имеет место репликация базы данных), то можно применить стандартные алгоритмы обеспечения консистентности такие как Paxos или Raft. Такие транзакции называются гомогенными. Если данные обновляются несколькими сервисами (то есть имеет место гетерогенная транзакция), то как тут как раз и начинаются сложности, о которых мы говорили выше.

С одной стороны мы можем все-таки обойти необходимость обеспечения распределенной транзакции путем стремления к service-based архитектуры (объединяем сервисы таким образом, чтобы транзакция была гомогенная). Такое решение не очень каноничное с точки зрения принципов микросервисной архитектуры, но зато оно технически намного проще из-за чего часто применяется на практике. С другой стороны мы можем оставить каноничные микросервисы, но при этом применить один из механизмов обеспечения распределенных транзакций: двухфазный коммит или сагу. В этой статье будет изучен первый вариант, а второй мы обсудим в следующий раз.

Двухфазный коммит


Механизм предельно прост: есть некоторый transaction manager, который собственно оркестрирует транзакцию. На первом этапе (prepare) transaction manager подает соответствующую команду для resource manager'ов, по которой они в свои журналы записывают данные, которые будут закоммичены. Получив подтверждение ото всех resource manager'ов об успешном завершении первого этапа, transaction manager начинает второй этап и подает следующую команду (commit), по которой resource manager'ы применяют принятые ранее изменения.

Несмотря на кажущуюся простоту, такой подход обладает рядом недостатков. Во-первых, если хотя бы один resource manager даст сбой на втором этапе, вся транзакция должна быть отменена. Таким образом, нарушается один из принципов микросервисной архитектуры устойчивость к отказам (когда мы приходили к распределенной системе, мы сразу закладывались на то, что отказ в ней является нормой а не исключительной ситуацией). Более того, если отказов будет много (а их будет много), то процесс отмены транзакций необходимо будет автоматизировать (в том числе и писать транзакции, откатывающие транзакции). Во-вторых, сам transaction manager является единой точкой отказа. Он должен уметь транзакционно выдавать id-шники транзакциям. В-третьих, поскольку хранилищу подаются специальные команды, логично предположить, что хранилище должно уметь это делать, то есть соответствовать стандарту XA, а не все современные технологии ему соответствуют (такие брокеры как Kafka, RabbitMQ и NoSQL решения как MongoDB и Cassandra не поддерживают двухфазные коммиты).

Вывод, напрашивающийся из всех этих факторов, был отлично сформулирован Крисом Ричардсоном: 2PC not an option (двухфазный коммит не вариант).

Вывод


Мы разобрались почему распределенные транзакции являются основной технической болью микросервисной архитектуры и поговорили о различных вариантах решения данной задачи, детально обсудили механизм двухфазного коммита.



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




Читать ещё:


Подробнее..

Impact Analysis 6 шагов, которые облегчат тестирование изменений

25.01.2021 22:13:40 | Автор: admin
Содержание
  • Что такое Impact Analysis?

  • Когда нужно проводить Impact Analysis?

  • Для чего нужно проводит Impact Analysis?

  • Как провожу Impact Analysis я?

    • 1. Изучение issue\ticket\bug\change request *

    • 2. Чтение emails **

    • 3. Разговор с разработчиками **

    • 4. Изучение места, где было сделано изменение ***

    • 5. Изучение описания изменений ***

    • 6. Исследование кода изменений *****

  • Почему я решила написать об этом?

Что такое Impact Analysis?

Прежде всего, Impact Analysis (импакт анализ) - это исследование, которое позволяет указать затронутые места (affected areas) в проекте при разработке новой или изменении старой функциональности, а также определить, насколько значительно они были затронуты.

Затронутые области требуют большего внимания во время проведения регрессионного тестирования.

Отмечу сразу, чтобы не пугать QA: импакт анализ не есть "чтение кода". Он включает в себя и иные способы исследования.

Когда нужно проводить Impact Analysis?

Импакт анализ может быть полезным в следующих случаях:

  • есть изменения в требованиях;

  • получен запрос на внесение изменений в продукт;

  • ожидается внедрение нового модуля или функциональности в существующий продукт;

  • каждый раз, когда есть изменения в существующих модулях или функциональностях продукта.

Как мы знаем, в настоящее время продукты становятся всё более большими и комплексными, а компоненты всё чаще зависят друг от друга. Изменение строчки кода в таком проекте может "сломать" абсолютно всё.

Developers are fixing Production IssueDevelopers are fixing Production Issue

Для чего нужно проводит Impact Analysis?

Информация о взаимосвязи и взаимном влиянии изменений могут помочь QA:

  • сфокусироваться на тестировании функциональности, где изменения были представлены;

  • принять во внимание части проекта, которые были затронуты изменениями и, возможно, пострадали;

  • не тратить время на тестирование тех частей проекта, которые не были затронуты изменениями.

Как провожу Impact Analysis я?

  1. Изучаю issue\ticket\bug\change request *.

  2. Читаю email переписку **.

  3. Разговариваю в разработчиками **.

  4. Смотрю на место где было изменение (commit place) ***.

  5. Смотрю на описание изменения (commit description) ***.

  6. Смотрю на изменения в коде *****.

'*' показывает "уровень сложности" этого действия. Как видно, только "шаг 6" требует умения читать код, с "шагами 1-5" способен справится QA и без знаний языком программирования.

1. Изучение issue\ticket\bug\change request *

Самое основное и базовое (поэтому и сложность *), что нужно сделать, - это внимательно изучить ишью в баг-трекинговой системе. Следует обратить внимание на все поля, особенно:

  • Steps To Repeat;

  • Description;

  • Additional Background Information;

  • Attachment;

Некоторые важные условия или особенности, описанные в ишью, помогут вам идентифицировать область тестирования. Например, при внимательном прочтении ишью, вы обнаружили, что в 'Additional Background Information' стоит пометка, что проблема воспроизводится только при использовании HTTPs. Поэтому для себя можно отметить, что при тестировании неплохо было бы проверить и случай с HTTP.

2. Чтение emails

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

  • больше деталей от заказчиков;

  • результаты исследований от других членов команды;

  • список похожих проблем;

  • картинки, графики, схемы и другое.

Сложность этого действия "**", только потому, что в переписках может быть больше технической информации или "сленга" разработчиков.

Why wasn't it mentioned in the issue?!Why wasn't it mentioned in the issue?!

3. Разговор с разработчиками **

QAs and Developers QAs and Developers

Во время тестирования изменений ваша цель - найти как можно больше "поломавшегося" и поэтому стоит смело подойти к разработчикам, к тем "кто возможно поломал" и спросить напрямую: "Ты сделал изменения, подскажи, на что они могут повлиять, какие области\модули мне нужно проверить тщательнее". Хороший разработчик, понимающий, что чем раньше баг будет обнаружен, тем дешевле будет его исправить, поможет вам советом, даже если будет абсолютно уверен в своих сделанных изменениях.

4. Изучение места, где было сделано изменение ***

Изменения, которые сделаны, должны быть куда-то внесены. В моём случае, это git, где достаточно легко можно определить место, где были сделаны изменения. Под "местом" я понимаю "конкретный файл, конкретная функция\метод, конкретный модуль". И следовательно, это "место" (этот модуль, функциональность) следует перепроверить, протестировать на наличие регрессий.

File where changes areFile where changes are

Например, на картинке выше видно, что изменения были в 'ExtendedClassification' функциональности, поэтому хотя бы, Smoke Test для этой функциональности должен быть пройден.

Так же, если изменения были в каких-то клиентских файлах ( JS, HTML, CSS, etc.), то следует провести кроссбраузерное тестирование.

Сложность "***" - чтение кода всё ещё не требуется, но нужно иметь представление об архитектуре проекта.

5. Изучение описания изменений ***

Для того, чтобы QA могли описания изучать, сначала нужно добиться того, чтобы Developers начали писать грамотные и понятные описания изменений. В моём отделе мы придерживается следующего шаблона, для описания изменении (git commits):

Ticket number and title

- Bug:

{В чём состоит дефект, какое актуальное поведение системы?}

- Problem:

{первопричина дефекта, что в системе работает не так?}

- Fix:

{в чём состоит изменение}

Changes descriptionChanges description

Например, исходя из описания исходной проблемы "Логика не работает при версировании root ItemType" (изображение сверху), следует, что нужно проверить "данную логику при версировании root ItemType". И имея в наличие только bug и его описание, эта важная проверка не столь очевидна и может быть пропущена.

6. Исследование кода изменений *****

Тут всё банально просто - нужно читать код и представлять, что он делает. Конечно, не многим это под силу на данном этапе, но есть к чему стремиться. К тому же, он QA не требуется глубокого понимание кода. Базовых знаний программирования и поверхностных знаний ООП (в моём случае) вполне достаточно, чтобы представить use case, покрывающий основные функции этого кода.


Почему я решила написать об этом?

Недавно в отделе столкнулась с тем, что разработчик сделал кое-какие изменения и отправил это в тестирование QA. Тестировщик естественно принял решение провести регрессионное тестирование, но без особого разбора и исследований установил, что нужно пойти все регрессионные тесты, которые в сумме занимают 25ч (проверка доступов, отработка разной функциональности, проверка в разных браузерах). Когда я решила взглянуть на сделанные изменения, то обнаружила следующее:

ExampleExample

т.е. единственное изменение, которое было сделано, - это добавлена проверка, если ItemType не равен "HG_Modification Orger", то делай всё то же, что и делал раньше (сделай изменения и обнови окно), если ItemType равен "HG_Modification Orger", то пропусти (ничего не делай и просто обнови окно). Т.е. эти изменения никак не относятся к клиентской части (проверка в разных браузерах не нужна). Изменения никак не затрагивают доступы, отрисовку. Они затрагивают лишь определённую функциональность, которую нужно проверить для ItemType = "HG_Modification Orger" и для ItenType != "HG_Modification Orger". Эти проверки займут 30 минут в худшем случае. Но никак не 25 часов.

Это наглядный пример, как impact analysis помог уменьшить время проведения необходимого тестирование значительно.

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru