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

интервью

задний план

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

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

Ознакомьтесь с процессом собеседования

Интервьюер сначала нарисовал на бумаге такую ​​картинку:

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

Я ответил на вопрос, что в середине могут быть распределенные транзакции.Когда шаг 2 вызывает систему B, может быть тайм-аут, когда ответ завершается после обработки системы B, в результате чего система A ошибочно думает, что обработка B не удалось, что привело к системе A. Откат, есть несоответствие данных с системой B.

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

Затем он продолжил спрашивать: «Тогда есть ли у вас хорошие решения?»

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

Затем интервьюер продолжил спрашивать:Затем прерывается строка, в которой А звонит Б. Как вы справляетесь с этим в своем коде? Как сделать откат? Расскажите, как написан ваш код.

В этот момент я был ошеломлен.

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

что такое транзакция

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

Взяв в качестве примера пример перевода, со счета А необходимо перевести 100 юаней на счет Б, что включает как минимум две операции:

  1. Счет минус 100 юаней
  2. Счет B плюс 100 юаней

Для системы управления базой данных, которая поддерживает транзакции, необходимо гарантировать, что две вышеуказанные операции (вся «транзакция») могут быть завершены и не могут существовать. 100 юаней А вычитаются, а затем учетная запись Б не добавляется.

Транзакции базы данных включают четыре характеристики, а именно:

  • Атомарность: транзакция выполняется как единое целое, а содержащиеся в ней операции над базой данных выполняются либо все, либо ни одна из них. Для переводов счет A вычитает деньги, а счет B добавляет деньги, либо в одно и то же время успешно, либо в одно и то же время.
  • Непротиворечивость: транзакция должна обеспечивать изменение состояния базы данных из одного согласованного состояния в другое. Непротиворечивое состояние означает, что данные в базе данных должны удовлетворять ограничениям целостности.
  • Изоляция: при одновременном выполнении нескольких транзакций выполнение одной транзакции не должно влиять на выполнение других транзакций. Когда другие счета переводят деньги, они не могут повлиять на предыдущие транзакции между A и B, указанные выше.
  • Долговечность: изменения в базе данных, внесенные совершенными транзакциями, должны постоянно храниться в базе данных.

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

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

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

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

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

Почему нам необходимо обеспечить согласованность

Теория CAP

Есть такая широко распространенная теория в распределенных системах:Теорема CAP

Эта теорема возникла из гипотезы, предложенной Эриком Брюэром, ученым-компьютерщиком из Калифорнийского университета в Беркли, на семинаре 2000 года по принципам распределенных вычислений (PODC). Позже в 2002 году Сет Гилберт и Нэнси Линч из Массачусетского технологического института (MIT) опубликовали доказательство гипотезы Брюэра, превратив ее в теорему. [Из Википедии]

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

  • Последовательность
  • Доступность
  • Допуск перегородки

А распределенная система может удовлетворить не более двух из них.

Итак, каковы три пункта выше? Почему только два одновременно?

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

2.png

Допуск перегородки

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

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

Все в порядке, бро.

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

Если вы хотите обеспечить доступность, то узел с данными возвращает данные, а узел без данных возвращает null , будет казаться, что пользователь видит, что данные какое-то время есть, а данных какое-то время нет, тогда Там естьпоследовательностьПроблема.

Доступность

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

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

На самом деле, подумайте об этом, ZK строго реализует CP, а Eureka гарантирует AP.

На самом деле распределенные транзакции подчеркивают согласованность.

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

2PC

Прежде чем мы поговорим о 2PC, давайте посмотримХА Спецификациячто это?

ХА СпецификацияОписывает интерфейс между глобальным диспетчером транзакций и локальным диспетчером ресурсов. Цель спецификации XA — разрешить доступ к нескольким ресурсам (таким как базы данных, серверы приложений, очереди сообщений и т. д.) в рамках одной транзакции, чтобы свойства ACID оставались действительными для разных приложений.

XAиспользоватьДвухэтапная фиксация (2PC)чтобы гарантировать, что все ресурсы фиксируют или откатывают любую конкретную транзакцию одновременно.

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

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

3.png

В сервисе работают две библиотеки, как обеспечить успех транзакции?

Здесь мы вводим рамкиAtomikos, он понял эту процедуру XA. Посмотрите на код:

4.png

Конкретное место для кода GithubAtomikosJTATest: GitHub.com/и немного наркотиков/Лир…

Глядя на картинку выше, вау, Atomikos сам реализовал менеджер транзакций. Откуда у нас связь.

  • Первым шагом является запуск транзакции, а затем предварительная фиксация.И db1, и db2 предварительно выполняются в первую очередь.Примечание: здесь не совершается транзакция.
  • Второй шаг — это реальная транзакция фиксации, которая инициируется Atomikos, и в случае возникновения исключения инициируется операция отката.

У этого процесса нет двух персонажей, менеджера транзакций, менеджера ресурсов (мы тут база данных, или какие еще компоненты, очереди сообщений).

Весь процесс выполнения выглядит так:

5.png
На картинке выше — нормальная ситуация, а на картинке ниже — ситуация, в которой неисправна одна сторона.

6.png

Изображение из:Обработка транзакций XA:Woohoo.info Q.Can /article/ think-…, для подробного объяснения XA вы можете внимательно посмотреть. Весь процесс 2PC:

Этап 1 (этап отправки запроса):

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

Второй этап (представить этап реализации):

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

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

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

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

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

Надежная схема окончательной согласованности сообщений

На основе общего промежуточного программного обеспечения очереди сообщений

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

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

7.png

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

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

Далее продолжайте обрабатывать другую локальную логику.

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

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

Вот возможные проблемы и способы их решения на каждом этапе:

  1. Например, вprepareЕсли на этом этапе произойдет исключение, заказ здесь не будет успешно размещен. Но мы сказали, что мы здесь на основе надежной информации, и мы должны убедиться, что наша служба сообщений работает нормально.
  2. существуетcomfirmПроизошло исключение, в этот раз не удалось подтвердить отправку, но наш заказ был успешно размещен. В этом случае мы можем запустить временную задачу в независимой службе сообщений, чтобы регулярно запрашивать статус сообщения.initданные, переходим к обратному запросу, чтобы увидеть, существует ли номер заказа в системе заказов, если да, то мы устанавливаем сообщение наsendЗатем статус отправляется в очередь сообщений.Если будет запрошен несуществующий заказ, сообщение будет удалено напрямую. Итак, здесь наша система заказов должна предоставлять интерфейс для пакетных запросов, а система последующего потребления должна быть идемпотентной. Обеспечьте постоянство повторного потребления.
  3. Очередь сообщений теряет сообщения или нижестоящая система все время не может выполнить обработку, в результате чего сообщения не возвращаются.sendСообщение о состоянии. В настоящее время нам также нужна задача синхронизации, чтобы справиться с этим.sendСостояние состояния мы можем повторно отправить до успешного потребления последней системой.
  4. Наконец, на стороне потребителя, когда мы потребляем, если возникает исключение потребления или системная ошибка вызывает исключение. Затем мы также можем записать журнал здесь.Если это не проблема системного кода, она вызвана дрожанием сети, то в третьем случае выше система сообщений повторно отправит сообщение, и мы будем иметь дело с ним. Если он продолжает давать сбои, вам нужно подумать, действительно ли в вашем коде есть проблема или ошибка.
  5. Окончательный гарантийный план,бревно, есть проблема с обработкой данных человеческой плоти. Теперь, когда в нашей системе есть ошибки, нет возможности полагаться на машины для их решения текущими техническими средствами, и мы должны полагаться на себя. Насколько я знаю, сейчас на многих крупных заводах есть такие люди, которые специализируются на решении подобных задач и вручную модифицируют базу данных. Небольшие фабрики, на которых мы остались, в основном полагались на то, что мы сами напишем sql для изменения данных.Подумайте об этом, верно?

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

8.png

задача на время:

9.png

Реализация на основе RocketMQ

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

Блок-схема выглядит следующим образом:

10.png

Вот служба новостей, весь процесс основан на соответствии с вышеизложенным. Здесь не слишком сложно, пожалуйста, обратитесь к конкретной реализации кода:woohoo.brief.com/afraid/453 из 6 или 7 методов…, очень хорошо написано.

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

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

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

ТСС-решение

Весь процесс TCC разделен на три этапа, а именно «Попробовать», «Подтвердить» и «Отменить»:

  1. Пробный этап: этот этап посвящен обнаружению ресурсов каждой службы и блокировке или резервированию ресурсов.
  2. Подтвердить этап: Этот этап посвящен выполнению реальных операций в каждом сервисе.
  3. Отменить этап: Если есть ошибка в выполнении бизнес-метода какого-либо сервиса, то здесь требуется компенсация, то есть выполняется операция отката успешно выполненной бизнес-логики

Взяв в качестве примера перевод, при переводе денег между банками необходимо задействовать распределенные транзакции двух банков и перевести 1 блок из банка A в банк B. Если схема TCC используется для достижения:

11.png

Наверное идея такая:

  1. Пробный этап: Сначала заморозьте 1 блок на банковском счете А и добавьте 1 блок к средствам на банковском счете Б.
  2. Подтвердить этап: Для выполнения фактической операции передачи средств на банковском счете A вычитаются на 1 юаней, а средства на банковском счете B увеличиваются на 1 юаней.
  3. Отменить этап: Если операция какого-либо банка не удалась, ее необходимо откатить за компенсацию.Например, если банковский счет А был вычтен, но увеличение средств банковского счета Б не удалось, то средства банка банковский счет А должен быть добавлен обратно.

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

Возьмите пример реализации фреймворка ByteTCC, чтобы примерно описать описанный выше процесс, адрес примераgit ee.com/byte soft/by…

В начале банковский счет A и банковский счет B соответственно: сумма (количество) = 1000, заморожено (замороженная сумма) = 0

Трансфер с банковского счета для инициирования банковского счета B:

12.png

Попробуйте фазу: Сумма на банковском счете A уменьшается на 1, замороженная сумма увеличивается на 1, а замороженная сумма на банковском счете B увеличивается на 1.

13.png

В настоящее время:

  • Банковский счет: сумма = 1000 - 1 = 999, заморожено = 0 + 1 = 1
  • Банковский счет B: сумма = 1000, заморожено = 0 + 1 = 1

подтвердить этап: замороженная сумма на банковском счете A уменьшается на 1, сумма на банковском счете B увеличивается на 1, а замороженная сумма уменьшается на 1

14.png

В настоящее время:

  • Банковский счет: количество = 999, заморожено = 1 - 1 = 0
  • Банковский счет B: сумма = 1000 + 1 = 1001, заморожено = 1 - 1 = 0

отменить фазу: сумма банковского счета A + 1, замороженная сумма -1, замороженная сумма банка B -1

15.png

В настоящее время:

  • Банковский счет: сумма = 999 + 1 = 1000, заморожено = 1 - 1 = 0
  • B банковский счет: сумма = 1000, замороженный = 1 - 1 = 0

На этом этапе демонстрируется весь процесс, и все помнят запуск кода. На самом деле это довольно сложно.Интерфейсов для взаимодействия со всем бизнесом много.Представьте, что если мы используем много ТСС в нашем проекте для написания, а у вас есть?

Позвольте мне еще раз упомянуть теорию BASE.

Теория BASE — это аббревиатура трех фраз: «основно доступный», «мягкое состояние» и «в конечном счете непротиворечивый».

  1. В основном доступно: Относится к распределенной системе, допускающей частичную потерю доступности в случае непредсказуемых сбоев.
  2. Мягкое состояние: Refers to the intermediate state that allows data in the system to exist and believe that the existence of the intermediate state does not affect the overall availability of the system, ie, the process that allows the system to synchronize between data copies of different nodes. Задерживать.
  3. Конечная согласованность: подчеркивает, что все операции обновления данных могут в конечном итоге достичь согласованного состояния после периода синхронизации. Следовательно, суть эвентуальной непротиворечивости заключается в том, что системе необходимо обеспечить непротиворечивость конечных данных, и ей не нужно обеспечивать сильную согласованность системных данных в режиме реального времени.

Его основная идея заключается в следующем:

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

Давайте еще раз подумаем об этом, учетная запись в приведенной выше схеме TCC имеет замороженное поле, разработанноеfrozen, не так лиБАЗОВАЯ теорияСерединамягкое состояниеШерстяная ткань?

Наконец

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

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

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