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

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

50 голосов
/ 12 сентября 2011

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

Предположим, у меня есть две БД (A и B), использующие 2PC в двух разных местах. Прежде чем A и B будут готовы к совершению транзакции, обе базы данных сообщат менеджеру транзакций, что они готовы к фиксации. Таким образом, когда диспетчер транзакций будет подтвержден, он отправит сигнал A и B, сообщая им, что нужно продолжить.

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

Помните, A зафиксирован, а B нет, и мы используем 2PC (так что дизайн 2PC перестает работать, не так ли?)

Ответы [ 3 ]

60 голосов
/ 12 сентября 2011

при двухфазной фиксации

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

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

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

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

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

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

Приложение все еще должно иметь возможность восстановления после ошибки, но транзакция не может завершиться сбоем без уведомления приложения о несовместимом состоянии.

Семантика

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

  • Если менеджер ресурсов или сеть выходит из строя на этапе 2, Менеджер транзакций будет продолжать опрашивать менеджера ресурсов до это возвращается. Когда он снова подключается к менеджеру ресурсов он сообщит RM о совершении транзакции. Если RM возвращает ошибка в соответствии с «Неизвестным TxID» TM будет знать, что в RM существует проблема потери данных.

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

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

События потери данных после фиксации в менеджерах ресурсов не обрабатываются менеджером транзакций и являются функцией устойчивости RM.

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

  1. Обратите внимание, что сбой такого рода также может привести к потере данных из ранее зафиксированных транзакций. Двухфазная фиксация не гарантирует, что менеджеры ресурсов не могут потерять или повредить данные или что процедуры DR не испортятся.
3 голосов
/ 31 марта 2015

Ваш сценарий не единственный, когда все может пойти не так, несмотря на все усилия. Предположим, что и A, и B сообщили об «готовности к принятию» к TM, а затем кто-то отключает линию между TM и, скажем, B. B ожидает одобрения (или запрета) от TM, но он определенно выиграл не ждите вечно, пока ТМ не восстановит соединение (его собственные ресурсы, участвующие в транзакции, должны оставаться заблокированными / недоступными в течение всего времени ожидания по очевидным причинам). Поэтому, когда B слишком долго ждет своего вкуса, он будет принимать то, что называется «эвристическими решениями». То есть, он решит фиксировать или откатить независимо от TM, основываясь на том, ну, я не знаю, на что, но это не имеет значения. Должно быть очевидно, что любые такие эвристические решения могут отличаться от фактического решения о коммите, принятого TM.

2 голосов
/ 31 марта 2015

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

http://the -paper-trail.org / блог / консенсус-протоколы-три фазы фиксации /

Вот основные части этой статьи:

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

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

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

Последняя фаза протокола выполняет почти то же самое, что и первоначальная фаза «фиксация или прерывание» в 2PC. Если координатор получает подтверждение доставки сообщения «подготовиться к принятию» из всех реплик, тогда можно безопасно приступить к совершению транзакции. Однако, если доставка не подтверждена, координатор не может гарантировать, что состояние протокола будет восстановлено в случае его сбоя (если вы допускаете фиксированное число сбоев f, координатор может продолжить работу после получения f + 1. подтверждения). В этом случае координатор прервет транзакцию.

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

Так 3PC решает все наши проблемы? Не выйтиэ, но это близко.В случае сетевого раздела колеса скорее отрываются - представьте, что все реплики, которые получили «готовятся к фиксации», находятся на одной стороне раздела, а те, которые не были, - на другой.Затем оба раздела продолжат работу с узлами восстановления, которые соответственно фиксируют или прерывают транзакцию, и при слиянии сети система будет иметь несовместимое состояние.Таким образом, 3PC имеет потенциально небезопасные прогоны, как и 2PC, но всегда будет прогрессировать и, следовательно, удовлетворяет своим свойствам живучести.Тот факт, что 3PC не будет блокировать отказы одного узла, делает его более привлекательным для услуг, где высокая доступность важнее, чем низкие задержки.

...