2 Phase Commit
Алгоритм двухфазного коммита — классический централизованный оптимистичный алгоритм распределённого консенсуса из баз данных для подтверждения распределённых транзакций.
После того, как мы завершили транзакцию, её надо атомарно подтвердить на всех участниках. У каждой транзакции есть выделенный координатор (transaction coordinator). Алгоритм работает в две фазы:
- Запрос (request): координатор спрашивает каждого участника: "готов ли ты очень быстро завершить транзакцию?". Если кто-нибудь ответил "нет", то отменяем транзакцию. Если кто-то отвечает "да", то он должен уметь обеспечить завершение транзакции даже если упадёт и поднимается (например, все данные уже в журнале).
- Завершение: координатор принимает решение о закреплении (commit) или отмене (rollback) транзакции и записывает его в свою надёжную память, после чего рассылает всем решение. После этого можно сообщить о фиксации транзакции.
Ограничения
Так как это алгоритм консенсуса, к нему применима FLP.
Если у нас есть отказы узлов или связи, то 2PC будет ждать, пока связь не восстановится:
- Если отказ произошёл на первой фазе, то координатор может отменить транзакцию по таймауту.
- После того, как координатор перешёл на вторую фазу, он не имеет права успокоиться, пока не донесёт своё решение до всех узлов.
- Если узел отказал, а потом восстановился, то он спрашивает координатора, какое решение было принято. Если "да", то обязан закрепить транзакцию (т.е. координатор должен хранить все подтверждённые транзакции, которые подтвердили не все узлы).
- Если отказал координатор, то, если узел ответил "да", он не имеет права забить на транзакцию, пока координатор не восстановится.
Но алгоритм классический, простой, на практике неплохо работает, потому что сложно только с отказами координатора и отказами узлов на второй фазе (когда решение о коммите уже принято), а такое бывает не так часто.