Полное руководство по началу работы с микросервисами

база данных Микросервисы Архитектура сервер

Эта статья подробно расскажет обо всех аспектах микросервисов и познакомит вас с миром микросервисов. Эта статья длинная, всего 2,4 слова. Учащиеся с базовыми знаниями могут выбирать интересующие их главы для чтения.

Перепечатайте, пожалуйста, свяжитесь со мной!

В этой статье будет рассмотрено следующее:

  1. Обзор микросервисов

    1.1 Легко расширяется

    1.2 Простое развертывание

    1.3 Технологическая неоднородность

  2. Сегментация службы базы данных

    2.1 Что такое «подбиблиотека и подтаблица»?

    2.2 Несколько способов расширения базы данных

    2.3 Несколько способов подбиблиотеки и подтаблицы

    2.4 Проблемы, возникшие после введения промежуточного программного обеспечения подбазы данных и подтаблицы

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

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

    3.1 Что такое сделка?

    3.2 Четыре характеристики транзакции ACID

    3.3 Уровень изоляции транзакций

    3.4 Что такое распределенная транзакция?

    3.5 Теория CAP

    3.6 БАЗОВАЯ теория

    3.7 Кислотно-щелочной баланс

    3.8 Протокол распределенных транзакций

    3.9 Решения для распределенных транзакций

  4. Развертывание службы

    4.1 Непрерывная интеграция, непрерывное развертывание, непрерывная доставка

    4.2 Микросервисы и непрерывная интеграция

    4.3 Конструкции микросервисов

  5. использованная литература


1. Что такое микросервисы?

Сначала мы даем определение микросервисов, а затем даем подробное объяснение определения.

Микросервисы — это небольшие сервисы, которые могут работать независимо и работать вместе.

Из понятий мы можем выделить три ключевых слова: автономный, интероперабельный, маленький. Эти три слова очень кратко описывают основные функции микросервисов. Ниже мы подробно объясним эти три термина.

  1. Может работать независимо

    Микросервисы — это системы или процессы, которые можно разрабатывать, развертывать и запускать независимо друг от друга.

  2. можем работать вместе

    После принятия микросервисной архитектуры вся система делится на множество микросервисов, часто эти сервисы не являются полностью независимыми, и в бизнесе существует определенная связанность, то есть одному сервису может потребоваться использовать функции, предоставляемые другим сервисом. Это то, что называется «интероперабельностью». В отличие от приложений с одной службой, вызовы между несколькими микросервисами реализуются посредством связи RPC вместо локальных вызовов одной службы, поэтому стоимость связи относительно высока, но преимущества значительны.

  3. маленький, но красивый

    Идея микросервисов состоит в том, чтобы разделить огромную систему со сложными функциями на несколько независимых подсистем в соответствии с бизнес-функциями, которые называются «микросервисами». Каждый микросервис берет на себя только определенную ответственность, поэтому объем микросервисов «небольшой» по сравнению с односервисными приложениями. Маленький означает, что у каждой службы меньше обязанностей.Согласно принципу единой ответственности, при разработке системы мы должны попытаться сделать так, чтобы каждая служба несла только одну ответственность, чтобы достичь «высокой сплоченности» системы.

2. Преимущества микросервисов

1. Легко расширяется

В односервисном приложении, если текущая производительность достигает узкого места и не может поддерживать текущий бизнес-объем, обычно принимается режим кластера, то есть добавляются узлы кластера серверов, а односервисное приложение «копируется». " ко всем узлам, тем самым повышая общую производительность. Однако степень детализации этого расширения относительно грубая. Если проблемы с производительностью есть только у небольшой части системы, то в односервисном приложении нужно расширять все приложение, это метод простой и грубый, а правильное лекарство прописать невозможно. Когда мы используем микросервисную архитектуру, если производительность сервиса достигает узкого места, то нам нужно только увеличить количество узлов сервиса, а другие сервисы менять не нужно. Это расширение является более целенаправленным и может в полной мере использовать аппаратные и программные ресурсы компьютера. И только расширение одной службы оказывает меньшее влияние, поэтому вероятность системной ошибки ниже.

2. Простота развертывания

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

3. Технологическая неоднородность

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

Конечно, не все микросервисные системы обладают технической неоднородностью, для достижения технической неоднородности все сервисы должны предоставлять общие интерфейсы. Мы знаем, что в микросервисной системе интерфейсы RPC используются для связи между службами, и существует множество способов реализации связи RPC. Некоторые методы связи RPC тесно связаны с языком, например, технология Java RMI, которая требует, чтобы обе стороны взаимодействовали при разработке языка Java. Конечно, существуют также некоторые методы связи RPC, которые не зависят от языка, например REST, основанный на протоколе HTTP. Этот метод связи не накладывает никаких ограничений на язык, используемый обеими сторонами, если данные, передаваемые во время связи, соответствуют спецификации REST. Конечно, независимость от языка также означает отсутствие проверки типов на обеих сторонах коммуникации, что увеличивает вероятность ошибок. Следовательно, выбор независимого от языка метода связи RPC или метода связи RPC, тесно связанного с языком, должен быть обоснованно проанализирован в соответствии с реальным бизнес-сценарием.

2. Сервисная сегментация базы данных

2.1 Что такое «подбиблиотека и подтаблица»?

С наступлением эры больших данных объем данных в бизнес-системах увеличивается день ото дня, а емкость хранилища данных постепенно становится узким местом, влияющим на производительность системы. Текущий верхний предел хранения одной таблицы основной реляционной базы данных составляет 10 миллионов записей, и эта емкость хранилища, очевидно, не может удовлетворить требования к хранению бизнес-систем в контексте больших данных. С появлением таких концепций, как микросервисная архитектура и распределенное хранилище, проблема хранения данных постепенно стала поворотным моментом. Разделение данных — важное средство для постоянного хранения и эффективного запроса массивных данных. Процесс подтаблицы подбазы данных завершается на этапе проектирования системы, и разработчик системы должен разделить базу данных и таблицу данных, которые могут иметь узкие места в будущем, на несколько баз данных и несколько таблиц в соответствии с определенными правилами в соответствии с ожидаемый бизнес-объем системы. Эти базы данных и таблицы данных должны быть развернуты на разных серверах, чтобы распределить давление чтения и записи данных на каждый узел в кластере, повысить общую вычислительную мощность базы данных и избежать феномена узких мест при чтении и записи.

В настоящее время существует два способа сегментирования данных: дискретное сегментирование и непрерывное сегментирование.

Дискретное сегментирование заключается в хранении в сегментах после взятия по модулю определенного хэша поля данных. Пока алгоритм хеширования выбран правильно, данные будут равномерно распределены по разным сегментам, так что давление чтения и записи будет равномерно распределено по всем сегментам, а общие возможности чтения и записи данных будут улучшены. Однако дискретное хранилище требует строгой независимости между данными, но в реальных бизнес-системах это не так: данные между разными сегментами часто имеют определенную корреляцию, поэтому в некоторых сценариях требуются запросы на межсегментное соединение. Из соображений безопасности все современные реляционные базы данных не поддерживают соединения между базами данных. Следовательно, операция между базами данных должна выполняться промежуточным программным обеспечением подтаблицы подбазы данных, что сильно влияет на эффективность запроса данных. Кроме того, когда узкое место в емкости хранения данных необходимо расширить, правило дискретного сегментирования требует повторного выполнения операции хеширования по модулю над всеми данными, что, несомненно, становится важным фактором, ограничивающим масштабируемость системы. Хотя согласованное хеширование может в определенной степени уменьшить миграцию данных при расширении системы, проблема миграции данных по-прежнему неизбежна. Для системы, которая уже подключена к сети, слишком дорого останавливать внешние службы для переноса данных.

Второй метод шардирования данных — непрерывный шардинг, который может решить проблему миграции данных при расширении системы. Этот метод требует непрерывного хранения данных в соответствии со временем или с непрерывным автоинкрементным первичным ключом. Поэтому данные за определенный период времени или данные смежных первичных ключей будут храниться в одном сегменте. Когда необходимо добавить осколки, существующие осколки не будут затронуты. Таким образом, непрерывное сегментирование может решить проблему миграции данных, вызванную расширением. Однако время хранения данных и частота чтения и записи часто пропорциональны, то есть большое количество операций чтения и записи часто сосредоточено во вновь сохраняемой части данных, что приведет к горячим проблемам и не позволит достичь первоначальное намерение разделить давление чтения и письма.

2.2 Несколько способов расширения базы данных

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

  1. вертикальная библиотека

    Вертикальное разбиение базы данных — это разделение полной базы данных на несколько независимых баз данных в соответствии с бизнес-функциями.Эти базы данных могут работать на разных серверах, тем самым повышая общую производительность чтения и записи данных базы данных. Такой подход очень распространен в микросервисных архитектурах. Основная идея микросервисной архитектуры состоит в том, чтобы разделить полное приложение на несколько подсистем, которые могут работать независимо в соответствии с бизнес-функциями. Эти подсистемы называются «микросервисами», и каждая служба взаимодействует через интерфейс RPC. Эта структура делает систему менее связаны и легче расширяются. Концепция вертикального разделения базы данных совпадает с концепцией микросервисов. Исходные полные данные могут быть разделены на несколько независимых баз данных в соответствии с методом разделения системы на микросервисы, так что каждая микросервисная система имеет свою собственную независимую базу данных. чтобы избежать чрезмерной нагрузки на один узел базы данных и повлиять на общую производительность системы, как показано на следующем рисунке.

    title

  2. вертикальный стол

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

    title

  3. горизонтальная подтаблица

    Если количество записей в таблице слишком велико (более 10 миллионов записей), это сильно повлияет на производительность чтения и записи базы данных. Скорость чтения и записи достигла невыносимой для бизнеса скорости, поэтому для решения этой проблемы необходимо использовать горизонтальную подтаблицу. Таблица с горизонтальным разделением предназначена для разделения таблицы с множеством записей по горизонтали и разделения ее на несколько таблиц с одинаковой структурой. Например, предположим, что в настоящее время таблица заказов хранит данные о 20 миллионах заказов, что приводит к крайне низкой эффективности чтения и записи данных. В настоящее время метод горизонтальной таблицы можно использовать для разделения таблицы заказов на 100 таблиц заказов с одинаковой структурой, которые называются order_1, order_2..., order_100. Затем идентификатор пользователя, которому принадлежит заказ, может быть хеширован и равномерно сохранен в 100 таблицах, так что в каждой таблице будет храниться только 200 000 записей заказов, что значительно повышает эффективность чтения и записи заказа, как показано на следующий рисунок. Конечно, если разделяемые таблицы все хранятся на одном узле базы данных, то при слишком большом объеме запросов, ведь вычислительная мощность одного сервера ограничена, и узким местом системы все равно станет база данных, поэтому для решения этой проблемы существует решение для горизонтального сегментирования данных.

    title

  4. Горизонтальная подтаблица подбиблиотеки

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

    title

2.3 Несколько способов подбиблиотеки и подтаблицы

В настоящее время существует две широко используемые стратегии сегментирования данных, а именно непрерывная сегментация и дискретная сегментация.

  1. дискретный шардинг

    Дискретное сегментирование означает, что данные равномерно хранятся в каждом сегменте логической таблицы после разброса, так что операции чтения данных в одной и той же логической таблице равномерно распределяются по разным таблицам в разных библиотеках, тем самым повышая скорость чтения и записи. Дискретный шардинг обычно реализуется в виде хэша по модулю. Например, если логическая таблица имеет 4 сегмента, при чтении и записи данных промежуточное ПО сначала получит хеш-значение поля сегмента, а затем по модулю 4 вычислит сегмент, в котором находится запись. В этом методе, если хэш-алгоритм выбран правильно, сегментация данных будет относительно однородной, так что данные, считанные и записанные, будут распределяться по каждому сегменту равномерно, так что будет более высокая эффективность чтения и записи. Однако у этого метода есть и самый большой недостаток — высокая стоимость расширения базы данных. Таким образом, если вам нужно добавить больше осколков, исходный алгоритм осколков не сработает, и все записи должны будут пересчитывать местоположение осколка. Для уже подключенной системы стоимость переноса данных на уровне строк довольно высока, и, поскольку система все еще работает во время переноса данных, новые данные все еще генерируются, поэтому непротиворечивость данных в процессе переноса не может быть гарантирована. Если вы остановитесь и мигрируете, чтобы избежать этой проблемы, это неизбежно окажет огромное влияние на бизнес. Конечно, чтобы избежать миграции данных, если в начале шардируется больше шардов, придется нести более высокие затраты, что не по карману малым и средним компаниям.

  2. Последовательные осколки

    Под непрерывным сегментированием понимается хранение данных через определенные промежутки времени на одном и том же сегменте в соответствии с определенным правилом сегментирования. Например, в соответствии с разделением по времени каждый месяц создается физическая таблица. Затем при чтении и записи данных осколок, в котором находятся данные, можно найти непосредственно на основе текущего времени. Другой пример: он может быть сегментирован в соответствии с идентификатором записи. Этот метод сегментирования требует, чтобы идентификатор постоянно увеличивался. Поскольку максимальное количество записей, поддерживаемых одной таблицей в базе данных Mysql, составляет около 10 миллионов, мы можем хранить 10 миллионов записей на сегмент в соответствии с идентификатором записи.Когда текущее количество записей приближается к пределу хранилища, нам нужно только увеличить количество записей. Исходные данные не нужно мигрировать. Одно из самых больших преимуществ непрерывного сегментирования заключается в том, что его легко масштабировать, поскольку он не требует переноса данных. Однако самым большим недостатком непрерывного сегментирования является проблема горячих точек. При непрерывном сегментировании вновь вставленные данные концентрируются на одном и том же сегменте, а вновь вставленные данные часто считываются и записываются с высокой частотой, поэтому операции чтения и записи сосредоточены на последнем сегменте, что не может отражать преимущества сегментирования данных.

2.4 Проблемы, возникшие после введения промежуточного программного обеспечения подбазы данных и подтаблицы

  1. Межбиблиотечная операция

    В реляционных базах данных часто существуют ассоциации между несколькими таблицами, и нам нужно использовать операцию JOIN для соединения нескольких таблиц в процессе разработки. Однако, когда мы используем режим подтаблицы подбазы данных, производитель базы данных не разрешает операции JOIN между базами данных из соображений безопасности, поэтому, если две соединяемые таблицы разделены на разные базы данных, JOIN, предоставляемый SQL, не может Ключевые слова для обеспечения связи с таблицей нам может потребоваться завершить сборку и объединение данных с помощью нескольких запросов SQL на уровне бизнес-системы. С одной стороны, это увеличит сложность бизнес-системы, а с другой стороны, увеличит нагрузку на бизнес-систему. Поэтому, когда мы используем шардирование и режим шардирования, нам необходимо разумно задать стратегию шардирования и задать поля шардирования в соответствии с конкретным бизнес-сценарием, который будет представлен в последующих главах этой статьи.

  2. Распределенная транзакция

    Мы знаем, что база данных обеспечивает функцию транзакций для обеспечения согласованности данных. Однако эта транзакция предназначена только для одной базы данных, и поставщик базы данных не предоставляет транзакции между базами данных. Поэтому, когда мы используем подбазу данных и подтаблицу, нам необходимо реализовать распределенные транзакции на уровне бизнес-системы. Для получения подробной информации о распределенных транзакциях вы можете обратиться к другой статье автора.«Часто используемые решения для распределенных транзакций».

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

  • Cobar реализует прозрачные подрепозитории баз данных, позволяя разработчикам неосознанно манипулировать кластерами баз данных, тем самым упрощая модель программирования баз данных. Однако Cobar реализует только функцию подбиблиотеки и не реализует функцию подтаблицы. Подбаза данных может устранить узкие места, связанные с вводом-выводом, процессором и памятью в одной базе данных, но не может решить проблему чрезмерного объема данных в одной таблице. Кроме того, Cobar — это независимая операционная система, расположенная между системой приложений и системой баз данных, что увеличивает сложность развертывания и затраты на эксплуатацию и обслуживание.

  • Чтобы решить вышеуказанные проблемы, Cobar также запустил проект Cobar-Client, который представляет собой просто пакет Jar, установленный в приложении, а не независимую работающую систему, что в определенной степени снижает сложность системы. Однако, как и Cobar, он по-прежнему поддерживает только вложенные библиотеки, а не вложенные таблицы, и не поддерживает разделение чтения и записи.

  • MyCat — промежуточное ПО базы данных, основанное на вторичной разработке Cobar, по сравнению с Cobar добавляет функцию разделения чтения и записи и исправляет некоторые ошибки Cobar. Однако MyCat, как и Cobar, представляет собой систему, которую необходимо развертывать независимо, поэтому она усложнит развертывание и повысит стоимость последующей эксплуатации и обслуживания системы.

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

Как мы все знаем, база данных может достигатьместные дела, то есть вв той же базе, вы можете позволить набору операций выполняться правильно или вообще не выполняться. Здесь особо подчеркиваетсяместные дела, то есть текущая база данных может поддерживать транзакции только в одной базе данных. Однако текущая система часто использует архитектуру микросервисов, а бизнес-система имеет независимую базу данных, поэтому существует требование транзакции между несколькими базами данных, что называется «распределенной транзакцией». Итак, как нам реализовать распределенные транзакции, если текущая база данных не поддерживает транзакции между базами данных? В этой статье сначала будут рассмотрены основные концепции и теоретические основы распределенных транзакций, а затем представлены несколько часто используемых решений для распределенных транзакций. Без лишних слов, давайте начнем~

3.1 Что такое сделка?

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

3.2 Четыре характеристики транзакции ACID

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

  • атомарность

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

  • последовательность

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

  • изоляция

    Транзакции выполняются независимо друг от друга, они не мешают друг другу, и одна транзакция не видит данные другой запущенной транзакции.

  • Упорство

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

Примечание. Транзакции гарантируют только базу данных.Высокая надежность, то есть после возникновения проблемы в самой базе данных данные, представленные транзакцией, все еще могут быть восстановлены; и если это не сбой самой базы данных, например, поврежденный жесткий диск, данные, отправленные транзакцией, могут быть восстановлены. Потерянный. Это принадлежит "высокая доступность' категория. Следовательно, транзакции могут гарантировать только «высокую надежность» базы данных, а «высокая доступность» требует взаимодействия всей системы.

3.3 Уровень изоляции транзакций

Чтобы расширить здесь, транзакцияизоляцияСделайте подробное объяснение.

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

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

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

  1. обновление потеряно

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

  2. грязное чтение

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

  3. неповторяемое чтение

    Смысл неповторяемости: транзакция дважды считывает одну и ту же строку данных, но получает разные результаты. Он делится на следующие два случая:

    • Виртуальное чтение: в процессе чтения одной и той же записи транзакцией 1 дважды транзакция 2 изменяет запись, так что транзакция 1 считывает другую запись во второй раз.
    • Фантомное чтение: во время двух запросов транзакции 1 транзакция 2 выполняет операции вставки и удаления в таблице, поэтому результат второго запроса транзакции 1 изменяется.

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

3.3.2 Четыре уровня изоляции баз данных

База данных имеет следующие четыре уровня изоляции:

  1. Читать незафиксированные

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

  2. Чтение зафиксировано

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

  3. Повторяемое чтение Повторяемое чтение

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

  4. Сериализуемая сериализация

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

Чем выше уровень изоляции, тем лучше можно гарантировать целостность и согласованность данных, но тем больше влияние на параллельную производительность. Для большинства приложений предпочтительнее установить уровень изоляции системы базы данных на Read Committed. Он избегает грязных чтений и имеет хорошую производительность параллелизма. Хотя это может привести к проблемам параллелизма, таким как неповторяющееся чтение, фантомное чтение и второстепенные потерянные обновления, в отдельных случаях, когда такие проблемы могут возникать, приложение может управлять ими с помощью пессимистической блокировки или оптимистической блокировки.

3.4 Что такое распределенная транзакция?

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

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

  1. Пользователь просматривает продукты через систему продуктов, и когда он видит определенный продукт, он нажимает, чтобы разместить заказ.
  2. В этот момент система заказов сгенерирует заказ
  3. После успешного создания заказа платежная система предоставляет функцию оплаты
  4. Когда платеж будет завершен, система баллов добавит баллы пользователю.

Описанные выше шаги 2, 3 и 4 необходимо выполнить в одной транзакции. Для традиционных монолитных приложений очень просто реализовать транзакции, просто поместите эти три шага в метод A, а затем пометьте метод аннотацией Spring @Transactional. Spring гарантирует, что эти шаги либо все выполняются, либо не выполняются через поддержку транзакций базы данных. Но в этой микросервисной архитектуре эти три шага включают три системы и три базы данных.На данный момент мы должны внедрить некую черную технологию между базой данных и системой приложений для поддержки распределенных транзакций.

3.5 Теория CAP

Теория CAP утверждает, что в распределенной системе могут быть удовлетворены не более двух требований C, A и P.

Значение КАП:

  • C: Последовательность Последовательность

    Несколько копий одних и тех же данных идентичны в реальном времени.

  • А: Доступность

    Доступность: в течение определенного периода времени система возвращает четкий результат, система называется доступной.

  • P: Устойчивость к сбоям разделов Отказоустойчивость разделов

    Распространение одной и той же службы на несколько систем гарантирует, что когда одна система выйдет из строя, другие системы по-прежнему будут предоставлять ту же услугу.

Теория CAP говорит нам, что в распределенной системе мы можем выбрать не более двух из трех условий C, A и P. Так вот вопрос, какие два условия больше подходят для выбора?

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

  • Улучшить общую производительность

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

  • Достижение допуска разделения

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

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

Кроме того, доступность особенно важна для бизнес-систем. Сегодня, когда много говорят о пользовательском опыте, если бизнес-система часто имеет «системные аномалии» и время отклика слишком велико, это значительно снизит благосклонность пользователя к системе.В сегодняшней жесткой конкуренции в интернет-индустрии , конкурентов в той же сфере не будет Даже перечислять, периодическая недоступность системы может сразу вызвать переток пользователей к конкурентам. Следовательно, мы можем пожертвовать согласованностью только в обмен на функциональность системы.ДоступностьиДопуск перегородки. Это БАЗОВАЯ теория, которая будет представлена ​​ниже.

3.6 БАЗОВАЯ теория

Теория CAP говорит нам грустный, но вынужденный принять тот факт, что мы можем выбрать только два условия среди C, A, P. Для бизнес-систем мы часто жертвуем согласованностью в обмен на доступность системы и отказоустойчивость разделов. Однако здесь следует указать, что так называемая «жертва непротиворечивостью» заключается не в том, чтобы полностью отказаться от непротиворечивости данных, а в том, чтобы пожертвоватьсильная консистенцияобменслабая консистенция. Познакомимся с теорией BASE.

  • BA: базовый доступный
    • Вся система по-прежнему может гарантировать «доступность» при определенных форс-мажорных обстоятельствах, то есть по-прежнему может возвращать определенный результат в течение определенного периода времени. Просто разница между «в основном доступными» и «высокодоступными» заключается в следующем:
      • «Определенный период времени» может быть соответствующим образом продлен Когда проводится большая акция, время отклика может быть соответственно увеличено.
      • Вернуть страницу понижения версии некоторым пользователям Непосредственно верните страницу понижения версии некоторым пользователям, чтобы уменьшить нагрузку на сервер. Обратите внимание, однако, что возврат на страницу с пониженной версией по-прежнему возвращает явный результат.
  • S: Мягкое состояние: Мягкое состояние Состояние разных копий одних и тех же данных может не обязательно быть согласованным в реальном времени.
  • E: Возможная согласованность: Возможная согласованность Статус разных копий одних и тех же данных может не обязательно быть согласованным в режиме реального времени, но должна быть гарантирована его согласованность по истечении определенного периода времени.

3.7 Кислотно-щелочной баланс

ACID может гарантировать сильную согласованность транзакций, то есть данные непротиворечивы в режиме реального времени. В локальных транзакциях это не проблема, в распределенных транзакциях строгая согласованность сильно повлияет на производительность распределенных систем, поэтому теорию BASE можно использовать в распределенных системах. Однако разные бизнес-сценарии распределенных систем предъявляют разные требования к согласованности. Например, в сценарии транзакции требуется строгая согласованность. В этом случае необходимо следовать теории ACID. В таких сценариях, как отправка кода подтверждения SMS после успешной регистрации, согласованность в реальном времени не требуется, поэтому можно следовать теории BASE. . Поэтому необходимо искать баланс между ACID и BASE согласно конкретным бизнес-сценариям.

3.8 Протокол распределенных транзакций

Несколько протоколов для реализации распределенных транзакций описаны ниже.

3.8.1 Протокол двухфазной фиксации 2PC

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

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

1. Первый этап (этап голосования):

  1. Узел-координатор запрашивает у всех узлов-участников возможность выполнения операции фиксации (голосования) и начинает ждать ответов от каждого узла-участника.
  2. Узел-участник выполняет все операции с транзакциями до тех пор, пока запрос не будет инициирован, и записывает информацию об отмене и повторении в журнал. (Примечание: в случае успеха каждый участник уже выполнил транзакционную операцию)
  3. Каждый узел-участник отвечает на запрос, инициированный узлом-координатором. Если транзакционная операция узла-участника действительно успешна, он возвращает сообщение «согласовано»; если транзакционная операция узла-участника фактически терпит неудачу, он возвращает сообщение «отмена».

2. Второй этап (стадия выполнения фиксации):

Когда соответствующие сообщения, полученные узлом-координатором от всех узлов-участников, «согласны»:

  1. Узел-координатор отправляет запрос «формальной фиксации» всем узлам-участникам.
  2. Узел-участник официально завершает операцию и освобождает ресурсы, занятые в течение всего периода транзакции.
  3. Узел-участник отправляет сообщение «выполнено» узлу-координатору.
  4. Узел-координатор завершает транзакцию после получения сообщения «готово» от всех узлов-участников.

Если ответное сообщение, возвращенное каким-либо узлом-участником на первом этапе, имеет значение «Прервано» или узел-координатор не может получить ответное сообщение от всех узлов-участников до истечения времени ожидания запроса на первом этапе:

  1. Узел-координатор отправляет запрос «отката» всем узлам-участникам.
  2. Узел-участник использует ранее записанную информацию об отмене для выполнения отката и освобождения ресурсов, занятых в течение всей транзакции.
  3. Узел-участник отправляет сообщение «откат завершен» узлу-координатору.
  4. Узел-координатор отменяет транзакцию после получения сообщения «откат завершен» от всех узлов-участников.

Независимо от конечного результата, вторая фаза завершает текущую транзакцию.

Двухфазная фиксация, кажется, обеспечивает атомарные операции, но, к сожалению, двухфазная фиксация имеет несколько недостатков:

  1. Во время выполнения все участвующие узлы блокируют транзакции. Когда участник занимает общедоступный ресурс, другие сторонние узлы должны находиться в состоянии блокировки для доступа к общедоступному ресурсу.
  2. Участник терпит неудачу. Координатору необходимо указать дополнительный механизм тайм-аута для каждого участника, после которого вся транзакция завершается сбоем. (Не большая отказоустойчивость)
  3. Координатор не работает. Участник будет заблокирован навсегда. Для отказоустойчивости требуются дополнительные резервные машины. (Это может полагаться на протокол Paxos, который будет описан позже, для реализации HA)
  4. Проблема, которую нельзя решить на втором этапе: координатор вылетает после отправки сообщения коммита, и единственный участник, получивший это сообщение, тоже вылетает в это же время. Тогда, даже если координатор создаст нового координатора через протокол выборов, состояние этой транзакции будет неопределенным, и никто не знает, была ли совершена транзакция.

С этой целью Дейл Скин и Майкл Стоунбрейкер предложили протокол трехэтапной фиксации (3PC) в «Формальной модели восстановления после сбоев в распределенной системе».

3.8.2 Протокол трехфазной фиксации 3PC

В отличие от двухфазной фиксации, трехфазная фиксация имеет две точки изменения.

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

То есть, в дополнение к введению механизма тайм-аута, 3PC снова делит этап подготовки 2PC на два, так что трехэтапная отправка имеет три этапа: CanCommit, PreCommit и DoCommit.

1. Стадия подтверждения

Фаза CanCommit в 3PC на самом деле очень похожа на фазу подготовки в 2PC. Координатор отправляет участнику запрос на фиксацию, и участник возвращает ответ «Да», если участник может отправить, в противном случае возвращает ответ «Нет».

  1. бизнес-запрос

    Координатор отправляет участнику запрос CanCommit. Спросите, можно ли выполнить операцию фиксации транзакции. Затем начните ждать ответа участника.

  2. Ответить на отзыв

    После того, как участник получит запрос CanCommit, при нормальных обстоятельствах, если он считает, что транзакция может быть успешно выполнена, он вернет ответ «Да» и перейдет в состояние готовности. В противном случае отзыв Нет

2. Предкоммитный этап

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

  1. Отправьте предварительный запрос

    Координатор отправляет участнику запрос PreCommit и переходит в фазу «Подготовлено».

  2. Предварительная фиксация транзакции

    После того, как участник получит запрос PreCommit, операция транзакции будет выполнена, а информация об отмене и повторении будет записана в журнал транзакций.

  3. Ответить на отзыв

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

Если какой-либо участник отправляет координатору ответ No или после ожидания таймаута координатор не получает ответа от участника, то транзакция прерывается.

  1. отправить запрос на прерывание

    Координатор отправляет всем участникам запрос на прерывание.

  2. прервать транзакцию

    После того, как участник получает от координатора запрос на прерывание (или по истечении тайм-аута запрос от координатора не получен), исполнение транзакции прерывается.

3. этап выполненияНа этом этапе выполняется отправка реальной транзакции, которую также можно разделить на следующие две ситуации.

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

3.1 Выполнение коммита

  1. отправить запрос на отправку

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

  2. фиксация транзакции

    После того, как участник получает запрос doCommit, выполняется формальная фиксация транзакции. И освободите все ресурсы транзакции после завершения транзакции.

  3. Ответить на отзыв

    После фиксации транзакции координатору отправляется ответ Ack.

  4. завершить транзакцию

    После того, как координатор получит ответы подтверждения от всех участников, транзакция завершается.

3.2 Прерывание транзакцииЕсли координатор не получает ответ ACK, отправленный участником (может случиться так, что получатель не отправляет ответ ACK, или время ответа истекло), будет выполнена транзакция прерывания.

  1. отправить запрос на прерывание

    Координатор отправляет всем участникам запрос на прерывание.

  2. откат транзакции

    После получения запроса на прерывание участник использует информацию об отмене, записанную на этапе 2, для выполнения операции отката транзакции и освобождает все ресурсы транзакции после завершения отката.

  3. результаты обратной связи

    После того, как участник завершает откат транзакции, он отправляет ACK-сообщение координатору

  4. прервать транзакцию

    После того, как координатор получает сообщение ACK, возвращенное участником, транзакция прерывается.

3.9 Решения для распределенных транзакций

Решения для распределенных транзакций следующие:

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

3.9.1 Сценарий 1: глобальная транзакция (модель DTP)

Глобальные транзакции реализованы на основе модели DTP. DTP — это модель распределенных транзакций, предложенная организацией X/Open — эталонная модель обработки распределенных транзакций X/Open. В нем указано, что для реализации распределенных транзакций требуются три роли:

  • AP: система приложений приложений

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

  • ТМ: Менеджер транзакций Менеджер транзакций

    • Реализация распределенных транзакций завершается диспетчером транзакций, который предоставляет интерфейс управления распределенными транзакциями для вызова нашей бизнес-системы. Эти интерфейсы называются интерфейсами TX.
    • Диспетчер транзакций также управляет всеми диспетчерами ресурсов и отправляет эти диспетчеры ресурсов через предоставляемый ими интерфейс XA для реализации распределенных транзакций.
    • DTP — это просто набор спецификаций для реализации распределенных транзакций, и он не определяет, как реализовать распределенные транзакции.TM может реализовывать распределенные транзакции с использованием таких протоколов, как 2PC, 3PC и Paxos.
  • RM: Менеджер ресурсов Менеджер ресурсов

    • Объекты, которые могут предоставлять службы данных, могут быть менеджерами ресурсов, такими как базы данных, ПО промежуточного слоя для сообщений, кэши и т. д. В большинстве сценариев база данных является диспетчером ресурсов в распределенных транзакциях.
    • Диспетчер ресурсов может обеспечить транзакционные возможности отдельной базы данных, а также возможности фиксации и отката базы данных через интерфейс XA, чтобы помочь диспетчеру транзакций реализовать распределенное управление транзакциями.
    • XA — это интерфейс, определяемый моделью DTP, который используется для предоставления диспетчеру транзакций возможностей диспетчера ресурсов (базы данных) для фиксации, отката и т. д.
    • DTP — это просто набор спецификаций для реализации распределенных транзакций, а конкретная реализация RM осуществляется поставщиками баз данных.
  1. Существует ли промежуточное ПО для распределенных транзакций на основе модели DTP?
  1. Каковы преимущества и недостатки модели DTP?

3.9.2 Вариант 2: Распределенная транзакция на основе службы надежных сообщений

Этот способ реализации распределенных транзакций должен быть реализован через промежуточное программное обеспечение сообщений. Предположим, что есть две системы, A и B, которые могут обрабатывать задачи A и B соответственно. В это время в системе А есть бизнес-процесс, и задача А и задача Б должны быть обработаны в одной и той же транзакции. Давайте представим реализацию этой распределенной транзакции на основе промежуточного программного обеспечения сообщений.

title

  • Прежде чем система A обработает задачу A, она сначала отправляет сообщение промежуточному программному обеспечению сообщений.
  • ПО промежуточного слоя сообщений сохраняет сообщение после его получения, но не доставляет его. В это время нижестоящая система B еще не знает о существовании сообщения.
  • После того, как промежуточное программное обеспечение сообщения успешно сохраняется, оно возвращает подтверждающий ответ системе А;
  • После того, как система A получит ответ с подтверждением, она может начать обработку задачи A;
  • После того, как задача A обработана, запрос Commit отправляется промежуточному программному обеспечению сообщений. После отправки запроса для системы А обработка транзакции завершена, и теперь она может обрабатывать другие задачи. Однако сообщение фиксации может быть потеряно во время передачи, поэтому промежуточное программное обеспечение сообщений не доставит сообщение в систему B, и система будет несогласованной. Эта проблема решается механизмом просмотра транзакций промежуточного программного обеспечения сообщений, который будет представлен ниже.
  • После того, как промежуточное программное обеспечение сообщений получает команду Commit, оно доставляет сообщение системе B, тем самым инициируя выполнение задачи B;
  • Когда задача B завершена, система B возвращает промежуточному программному обеспечению сообщения подтверждающий ответ, сообщая промежуточному программному обеспечению сообщений, что сообщение было успешно обработано.В это время распределенная транзакция завершена.

Из вышеописанного процесса можно сделать следующие выводы:

  1. Промежуточное программное обеспечение сообщений играет роль координатора распределенных транзакций.
  2. После того, как система А завершит задачу А, будет определенная разница во времени между выполнением задачи Б. В течение этой разницы во времени вся система находится в состоянии несогласованности данных, но эта кратковременная несогласованность допустима, поскольку через короткий промежуток времени система может снова поддерживать непротиворечивость данных, что удовлетворяет теории BASE.

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

title

  • Если системе А не удастся обработать задачу А, она отправит запрос на откат промежуточному программному обеспечению сообщений. Как и при отправке запроса на фиксацию, после того, как система А отправила его, она может считать, что откат выполнен, и может заниматься другими делами.
  • После получения запроса на откат ПО промежуточного слоя сообщений напрямую отбрасывает сообщение, не доставляя его системе Б, поэтому задача Б системы Б не будет запущена.

В этот момент система снова находится в согласованном состоянии, потому что ни задача A, ни задача B не выполняются.

И Commit, и Rollback, описанные выше, идеальны, но в реальных системах обе команды Commit и Rollback могут быть потеряны во время передачи. Итак, когда это происходит, как ПО промежуточного слоя сообщений обеспечивает согласованность данных? - Ответ заключается в механизме запроса тайм-аута.

title

В дополнение к реализации обычного бизнес-процесса, система А также должна предоставить интерфейс для запроса транзакций для вызова промежуточного программного обеспечения сообщений. Когда промежуточное программное обеспечение сообщений получает транзакционное сообщение, оно начинает отсчет времени.Если оно не получает команды фиксации или отката от системы А в течение периода ожидания, оно будет активно вызывать интерфейс запроса транзакции, предоставленный системой А, чтобы узнать о текущем состоянии система. . Интерфейс возвращает три результата:

  • Отправить

    Если получен статус «зафиксировано», сообщение доставляется в систему B.

  • откат

    Если получен статус «откат», сообщение сразу отбрасывается.

  • Обработка

    Если получен статус «в обработке», продолжайте ждать.

Механизм запроса тайм-аута промежуточного программного обеспечения сообщений может предотвратить несогласованность системы, вызванную потерей команд фиксации/отката в вышестоящей системе во время передачи, а также может сократить время блокировки вышестоящей системы.Вышестоящая система может обрабатывать другие системы до тех пор, пока при выполнении команды Commit/Rollback, не дожидаясь подтверждения. Потеря команд Commit/Rollback компенсируется механизмом запроса тайм-аута, который значительно сокращает время блокировки вышестоящей системы и улучшает параллелизм системы.

Поговорим о гарантии надежности процесса доставки сообщения. Когда вышестоящая система завершает задачу и отправляет команду Commit промежуточному программному обеспечению сообщения, она может обрабатывать другие задачи.В это время она может считать, что транзакция была завершена, а затем промежуточное программное обеспечение сообщения должно убедиться, что сообщение успешно использовано. нижестоящей системой. ! ** Так как же это делается? Это гарантируется процессом доставки промежуточного программного обеспечения сообщений.

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

Если сообщение потеряно во время процесса доставки или ответ подтверждения сообщения потерян на обратном пути, промежуточное программное обеспечение сообщения будет повторно доставлено после ожидания тайм-аута ответа подтверждения, пока нижестоящий потребитель не вернет успешный ответ потребления. Конечно, общее промежуточное ПО для сообщений может устанавливать количество и временной интервал повторных попыток сообщения.Например, если первая доставка не удалась, оно будет повторять попытку каждые пять минут, всего 3 попытки. Если доставка не удалась после 3 попыток, сообщение требует ручного вмешательства.

title

title

Некоторые учащиеся могут спросить: почему бы вам не откатить сообщение после того, как его доставка не удалась, а продолжать пытаться доставить его повторно?

Это включает в себя стоимость реализации всей системы распределенных транзакций. Мы знаем, что когда система A отправит команду Commit промежуточному программному обеспечению сообщений, она будет делать другие вещи. Если в это время доставка сообщения не удалась и ее нужно откатить, системе А необходимо заранее предоставить интерфейс отката, что, несомненно, увеличит дополнительные затраты на разработку и усложнит бизнес-систему. Целью проектирования бизнес-системы является минимизация сложности системы при условии обеспечения производительности, чтобы снизить затраты на эксплуатацию и обслуживание системы.

Я не знаю, обнаружили ли вы, что вышестоящая система A отправляет сообщение Commit/Rollback промежуточному программному обеспечению сообщения асинхронным способом, то есть, когда вышестоящая система отправляет сообщение, она может делать другие вещи, а затем отправлять и rollback полностью передаются промежуточному программному обеспечению сообщений для завершения и полностью доверяют промежуточному программному обеспечению сообщений, что оно должно быть в состоянии правильно завершить фиксацию или откат транзакции. Однако процесс доставки сообщений нижестоящим системам с помощью ПО промежуточного слоя сообщений является синхронным. То есть после того, как промежуточное программное обеспечение сообщений доставляет сообщение нижестоящей системе, оно блокируется и ждет, пока нижестоящая система успешно обработает задачу и вернет подтверждение, прежде чем отменить ожидание блокировки. Почему они несовместимы по дизайну?

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

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

Асинхронность может улучшить производительность системы, но увеличит ее сложность, тогда как синхронизация снижает параллелизм системы, но стоимость реализации ниже. Поэтому, когда требования к параллелизму не очень высоки или когда ресурсов сервера относительно много, мы можем выбрать синхронизацию, чтобы уменьшить сложность системы. Мы знаем, что промежуточное программное обеспечение сообщений является сторонним промежуточным программным обеспечением, независимым от бизнес-системы. Оно не связано напрямую с какой-либо бизнес-системой и напрямую не связано с пользователями. Обычно оно развернуто на независимом кластере серверов и имеет хорошую масштабируемость, поэтому не слишком беспокойтесь о его производительности.Если скорость обработки не может удовлетворить наши требования, вы можете увеличить машину, чтобы решить эту проблему. Более того, даже если есть определенная задержка в скорости обработки промежуточного программного обеспечения сообщений, это приемлемо, потому что представленная ранее теория BASE говорит нам, что мы стремимся к согласованности в конечном счете, а не согласованности в реальном времени, поэтому промежуточное программное обеспечение сообщений генерирует это. допустимо, чтобы задержка вызывала временные несоответствия в транзакциях.

3.9.3 Сценарий 3. Уведомление о максимальных усилиях (регулярная проверка)

Оповещение о лучших усилиях, также известное как регулярная корректура, фактически уже включено в схему 2. Здесь оно будет введено отдельно, в основном для целостности системы знаний. Это решение также требует участия промежуточного программного обеспечения сообщений, и процесс выглядит следующим образом:

title

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

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

  1. Промежуточному программному обеспечению сообщений не удалось доставить сообщение в нижестоящую систему.
  2. Системе восходящего потока не удалось отправить сообщение промежуточному программному обеспечению сообщений.

В первом случае в промежуточном программном обеспечении для сообщений есть механизм повторных попыток. Мы можем установить количество повторных попыток сообщения и интервал времени повтора в промежуточном программном обеспечении для сообщений. В случае сбоя доставки сообщения, вызванного нестабильностью сети, он часто повторяется несколько раз. После Это означает, что сообщение может быть успешно доставлено. Если доставка не удалась за пределами верхнего предела повторных попыток, ПО промежуточного слоя сообщений больше не будет доставлять сообщение, но будет записано в таблицу сообщений об ошибках. ПО промежуточного слоя сообщений должно предоставить интерфейс запроса для сообщения об ошибках Сообщения об ошибках нижестоящей системы периодически запрашиваются и используются, что называется «периодической корректурой».

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

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

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

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

3.9.4 Схема 4: TCC (двухступенчатый, компенсационный)

TCC — это Try Confirm Cancel, компенсирующая распределенная транзакция. Как следует из названия, TCC реализует распределенные транзакции в три этапа:

  • Попробуйте: попробуйте дело, которое нужно выполнить
    • Этот процесс не выполняет бизнес, а просто завершает проверку согласованности всех бизнесов и резервирует все ресурсы, необходимые для выполнения.
  • Подтвердить: выполнить бизнес
    • Этот процесс фактически начинает выполнять бизнес.Поскольку проверка непротиворечивости была завершена на фазе «Попытка», этот процесс выполняется напрямую без какой-либо проверки. А в процессе выполнения будут использоваться бизнес-ресурсы, зарезервированные на этапе Try.
  • Отменить: отменить выполненное дело
    • Если бизнес-выполнение терпит неудачу, оно переходит в фазу «Отмена», которая освобождает все занятые бизнес-ресурсы и откатывает операции, выполненные в фазе «Подтверждение».

Ниже приведен пример передачи, поясняющий процесс реализации распределенных транзакций TCC.

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

  • Try

    • Создайте поток передачи и установите статус потока нав сделке
    • Вычесть 100 юаней со счета пользователя А (зарезервированные бизнес-ресурсы)
    • После того, как попытка будет успешной, она войдет в стадию подтверждения.
    • Если в процессе Try произойдет какая-либо аномалия, он перейдет в стадию Cancel.
  • Confirm

    • Добавьте 100 юаней на счет пользователя B в красном конверте.
    • Установите статус потока натранзакция завершена
    • Если в процессе подтверждения возникает какая-либо аномалия, он переходит в стадию отмены.
    • Процесс Confirm выполняется успешно, после чего транзакция завершается.
  • Cancel

    • Увеличьте счет пользователя А на 100 юаней
    • Установите статус потока натранзакция не удалась

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

Глобальные транзакции TCC должны реализовывать глобальные транзакции на основе локальных транзакций RM.

Услуга TCC состоит из операций Try/Confirm/Cancel, Когда его служба Try/Confirm/Cancel выполняется, он обращается к диспетчеру ресурсов (далее именуемый RM) для доступа к данным. Эти операции доступа должны участвовать в локальной транзакции RM, так что измененные данные либо фиксируются, либо откатываются.

Это не сложно понять, рассмотрим следующий сценарий:

title

Если предположить, что служба B на рисунке не основана на локальных транзакциях RM (взяв в качестве примера RDBS, ее можно смоделировать, установив для автоматической фиксации значение true), то после сбоя операции [B:Try] в середине выполнение, структура транзакций TCC впоследствии решает откатить глобальную транзакцию, [B:Cancel] необходимо определить, какие операции в [B:Try] были записаны в БД, а какие не были записаны в БД: что бизнес [B:Try] имеет 5 операций записи в базу данных, бизнес [B:Cancel] ] должен определить, допустимы ли пять операций одну за другой, и выполнить обратную операцию для допустимых операций.

К сожалению, поскольку бизнес [B:Cancel] также имеет n (0

Напротив, для транзакций TCC, основанных на локальных транзакциях RM, с этой ситуацией легко справиться: операция [B:Try] не может быть выполнена в середине, и структура транзакций TCC может напрямую откатить свое участие в локальных транзакциях RM. Когда последующая структура транзакций TCC решает откатить глобальную транзакцию, зная, что «локальная транзакция RM, участвующая в операции [B:Try], была отменена», нет необходимости выполнять операцию [B:Cancel] вообще. .

Другими словами, когда структура транзакций TCC реализуется на основе локальных транзакций RM, операция отмены услуги типа TCC либо выполняется, либо не выполняется, и нет необходимости рассматривать частичное выполнение.

Структура транзакций TCC должна обеспечивать гарантию идемпотентности для службы подтверждения/отмены.

Обычно считается, что идемпотентность службы относится к нескольким (n>1) запросам к одной и той же службе и одному (n=1) запросу к ней, оба из которых имеют одинаковые побочные эффекты.

В модели транзакций TCC бизнес-подтверждение/отмена может вызываться неоднократно по многим причинам. Например, глобальная транзакция будет вызывать бизнес-логику подтверждения/отмены каждой службы TCC при фиксации/откате. При выполнении этих услуг подтверждения/отмены могут возникать сбои, такие как сбои в сети, что делает невозможным завершение глобальных транзакций. Следовательно, механизм восстановления после сбоя по-прежнему будет повторно отправлять/откатывать эти незавершенные глобальные транзакции в будущем, так что бизнес-логика подтверждения/отмены каждой службы TCC, участвующей в глобальной транзакции, будет вызываться снова.

Поскольку бизнес Confirm/Cancel может вызываться несколько раз, его идемпотентность должна быть гарантирована. Итак, гарантия идемпотентности должна быть предоставлена ​​структурой транзакций TCC? Или бизнес-система должна сама обеспечивать идемпотентность? На мой взгляд, гарантия идемпотентности должна быть обеспечена структурой транзакций TCC. Если эта проблема возникает только у нескольких сервисов, то возможно, что виновата бизнес-система; однако это своего рода общественная проблема, и нет сомнений в том, что бизнес-подтверждение/отмена всех сервисов TCC имеет проблему идемпотентности. . Публичные проблемы сервисов ТСС должны решаться структурой транзакций ТСС, более того, учитывая вопросы, которые необходимо учитывать, когда бизнес-система ответственна за идемпотентность, будет обнаружено, что это, несомненно, увеличивает сложность бизнес-системы.

4. Развертывание службы

Когда мы завершим разработку бизнес-кода, нам нужно перейти к этапу развертывания. В процессе развертывания мы представим непрерывную интеграцию, непрерывную доставку, непрерывное развертывание и объясним, как их использовать в микросервисах.

4.1 Непрерывная интеграция, непрерывное развертывание, непрерывная доставка

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

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

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

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

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

Описанный выше процесс охватывает непрерывную интеграцию, непрерывную доставку и непрерывное развертывание, поэтому давайте представим эти три концепции с теоретической точки зрения.

4.1.1 Непрерывная интеграция

«Интеграция» относится к процессу слияния измененного/добавленного кода в репозиторий кода, а «непрерывная интеграция» относится к высокой частоте слияния кода. Какая от этого польза? Вы можете подумать об этом, если частота интеграции кода станет выше, объем кода для каждой интеграции станет меньше, потому что модульное тестирование будет выполняться при каждой интеграции, поэтому, когда возникает проблема, масштаб проблемы будет сокращено.Он сужен, чтобы вы могли быстро определить, где вы ошиблись, что упрощает поиск проблемы. Кроме того, частая интеграция может выявить проблемы раньше, что обходится дешевле. Поскольку в тестировании программного обеспечения существует такой закон, время пропорционально стоимости исправления ошибок, то есть чем больше время, тем больше стоимость исправления ошибок. Поэтому непрерывная интеграция позволяет находить проблемы как можно раньше и вовремя их устранять, что очень важно для качества программного обеспечения.

4.1.2 Непрерывное развертывание

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

4.1.3 Непрерывная доставка

Когда система прошла все тесты, она может быть развернута в рабочей среде. Этот процесс известен как «доставка». «Непрерывная доставка» означает, что каждая версия конструкции может быть подключена к сети, что требует автоматического запуска ряда процессов, таких как сборка, тестирование, развертывание и доставка, всякий раз, когда в базе кода появляется новая версия. Когда сборка не проходит тест на определенном этапе, разработчик должен немедленно решить проблему и перестроить ее, чтобы убедиться, что каждая версия сборки имеет право на запуск и может быть развернута в производственной среде в любое время.

4.2 Микросервисы и непрерывная интеграция

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

4.2.1 Мультисборка с одним репозиторием

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

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

Этот шаблон непрерывной интеграции явно нецелесообразен в микросервисной архитектуре. Во-первых, в системе может быть много сервисных компонентов, и если коды этих сервисов хранятся в одном репозитории кодов, то программист, скорее всего, модифицировал код сервиса Б по небрежности при разработке кода сервиса А. В то же время риски безопасности будут возникать после построения службы B. Если эта проблема будет обнаружена до того, как служба B будет подключена к сети, это будет хорошо, но это, несомненно, увеличит дополнительную нагрузку, но если эта проблема будет скрыта, это приведет к Предыдущий тест Вариант использования не охвачен, поэтому услуга Б вынесет эту проблему в производственную среду, что может принести огромные убытки предприятию. Поэтому в микросервисной архитектуре старайтесь выбирать режим мультибиблиотеки с несколькими сборками, чтобы добиться непрерывной интеграции, что обеспечит большую безопасность.

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

4.2.2 Несколько библиотек и несколько сборок

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

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

4.3 Конструкции микросервисов

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

4.3.1 Платформенные конструкции

Конструкции платформы относятся к конструкциям, сгенерированным конкретной платформой, например, пакеты Jar и пакеты War, сгенерированные платформой JVM, яйца, сгенерированные Python, и т. д. — все это конструкции платформы. Однако конструкция платформы должна быть развернута в конкретном контейнере, например, война должна выполняться в контейнере сервлетов, а контейнер сервлетов зависит от среды JVM. Таким образом, для развертывания сборок платформы вам необходимо предоставить им среду, в которой они должны работать.

4.3.2 Конструкции операционной системы

Конструкция операционной системы состоит в том, чтобы упаковать систему в исполняемую программу операционной системы, такую ​​как RPM-пакет CentOS, MSI-пакет Windows и т. д. Эти установочные пакеты могут быть установлены и запущены непосредственно в операционной системе. Но, как и сборки платформы, сборки операционной системы часто должны зависеть от других сред, поэтому перед развертыванием также необходимо создать зависимости, необходимые для пакета установки. Кроме того, сложность настройки построения операционной системы относительно высока, а стоимость построения относительно высока, поэтому этот метод обычно не используется, а здесь он только представлен.

4.3.3 Конструкции изображения

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

Мы можем понимать образ как небольшую операционную систему, которая содержит все зависимости, необходимые для работы системы, и развертывает систему в этой «операционной системе». Таким образом, когда платформа непрерывной интеграции создает образ, она может запускать его напрямую без установки каких-либо зависимостей, что значительно упрощает сборку. Однако образ обычно относительно большой, да и процесс сборки образа тоже долгий, поэтому, когда мы публикуем сгенерированный образ с сервера непрерывной интеграции на сервер развертывания, это займет много времени, что, несомненно, снижает эффективность работы. развертывание. К счастью, появление Docker решило эту проблему. Платформе непрерывной интеграции не нужно генерировать образ в процессе создания, а нужно только создать файл Dockerfile образа. Dockerfile использует команды для определения того, что содержит образ, и процесса создания образа. Поэтому серверу непрерывной интеграции нужно только опубликовать этот файл образа меньшего размера на сервере развертывания. Затем сервер развертывания создаст образ на основе файла Dockerfile с помощью команды сборки docker и создаст контейнер образа для завершения развертывания службы.

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

5. Ссылки

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

Жизнь за пределами распределенных транзакций: мнение отступника

Небольшие размышления о том, как реализовать структуру распределенных транзакций TCC.

How can a requestor ensure a consistent outcome across multiple, independent providers

О распределенных транзакциях, двухфазном протоколе фиксации, трехфазном протоколе фиксации

Three-phase commit protocol

Руководство по выбору стека технологий микросервисной архитектуры

Анализ сценариев применения микросервисной архитектуры

Несколько распространенных форм подбиблиотеки и подтаблицы и возможные трудности