2 단계 커밋
저는 대부분의 사람들이 2PC (2 단계 커밋 프로토콜)가 무엇인지, Java 또는 대부분의 현대 언어에서 사용하는 방법을 알고 있다고 생각합니다. 기본적으로 두 개 이상의 DB가있을 때 트랜잭션이 동기화되었는지 확인하는 데 사용됩니다.
두 개의 다른 위치에서 2PC를 사용하는 두 개의 DB (A 및 B)가 있다고 가정합니다. A와 B가 트랜잭션을 커밋 할 준비가되기 전에 두 DB는 트랜잭션 관리자에게 다시 커밋 할 준비가되었다고보고합니다. 따라서 트랜잭션 관리자가 확인되면 A와 B에게 다시 진행하라는 신호를 보냅니다.
여기 내 질문이 있습니다. A가 신호를 받고 트랜잭션을 커밋했다고 가정 해 보겠습니다. 모든 것이 완료되면 B는 똑같은 작업을 수행하지만 누군가 전원 케이블을 뽑아 전체 서버가 종료됩니다. B가 다시 온라인 상태가되면 B는 무엇을합니까? 그리고 B는 그것을 어떻게합니까?
A는 커밋되었지만 B는 그렇지 않으며 2PC를 사용하고 있다는 것을 기억하십시오 (2PC의 디자인이 작동하지 않습니까?)
2 단계 커밋에서
2 단계 커밋은 분산 트랜잭션이 실패 할 수 없음을 보장하지 않지만 TM이 인식하지 않으면 자동으로 실패 할 수 없음을 보장합니다.
B가 트랜잭션을 커밋 할 준비가 된 것으로보고하려면 B는 트랜잭션이 영구 저장소에 있어야합니다 (즉, B는 트랜잭션이 모든 상황에서 커밋 될 수 있음을 보장 할 수 있어야 함). 이 상황에서 B는 트랜잭션을 지속했지만 트랜잭션 관리자는 B가 커밋을 완료했음을 확인하는 메시지를 B로부터 아직받지 못했습니다.
트랜잭션 관리자는 B가 다시 온라인 상태가되면 B를 다시 폴링하고 트랜잭션 커밋을 요청합니다. B가 이미 트랜잭션을 커밋 한 경우 트랜잭션이 커밋 된 것으로보고합니다. B가 아직 트랜잭션을 커밋하지 않은 경우 트랜잭션을 이미 유지 했으므로 트랜잭션을 커밋 할 수있는 위치에 있습니다.
이 상황에서 B가 실패하려면 데이터 또는 로그 항목이 손실 된 치명적인 실패가 발생해야합니다. 트랜잭션 관리자는 B가 성공적인 커밋을보고하지 않았 음을 여전히 알고 있습니다. 1
실제로 B가 더 이상 트랜잭션을 커밋 할 수없는 경우 B를 빼앗은 재해로 인해 데이터가 손실되었음을 의미하고 TM이 인식하지 못한 TxID를 커밋하도록 요청했을 때 B가 오류를보고합니다. 커밋 가능한 상태라고 생각하지 않았습니다.
따라서 2 단계 커밋은 치명적인 오류가 발생하는 것을 방지하지 않지만 실패가 눈에 띄지 않게되는 것을 방지합니다. 이 시나리오에서 트랜잭션 관리자는 B가 커밋 할 수없는 경우 응용 프로그램에 오류를 다시보고합니다.
애플리케이션은 여전히 오류에서 복구 할 수 있어야하지만 애플리케이션이 불일치 상태를 인식하지 않으면 트랜잭션이 자동으로 실패 할 수 없습니다.
의미론
리소스 관리자 또는 네트워크가 1 단계에서 다운되면 트랜잭션 관리자는 치명적인 오류 (리소스 관리자에 연결할 수 없음)를 감지하고 하위 트랜잭션을 실패로 표시합니다. 네트워크가 백업되면 모든 참여 리소스 관리자에서 트랜잭션이 중단됩니다.
리소스 관리자 또는 네트워크가 2 단계에서 다운되면 트랜잭션 관리자는 백업 될 때까지 리소스 관리자를 계속 폴링합니다. 리소스 관리자에 다시 연결되면 RM에게 트랜잭션을 커밋하도록 지시합니다. RM이 '알 수없는 TxID'줄을 따라 오류를 반환하면 TM은 RM에 데이터 손실 문제가 있음을 인식합니다.
TM이 1 단계에서 다운되면 클라이언트는 TM이 백업 될 때까지 차단됩니다. 단, 시간이 초과되거나 네트워크 연결이 끊어져 오류가 발생하지 않습니다. 이 경우 클라이언트는 오류를 인식하고 재 시도하거나 중단 자체를 시작할 수 있습니다.
TM이 2 단계에서 다운되면 TM이 다시 작동 할 때까지 클라이언트를 차단합니다. 이미 트랜잭션을 커밋 가능한 것으로보고했으며, TM이 백업 될 때까지 차단 될 수 있지만 클라이언트에 치명적인 오류가 표시되지 않아야합니다. TM은 여전히 트랜잭션을 커밋되지 않은 상태로 유지하고 RM을 폴링하여 백업 될 때 커밋합니다.
리소스 관리자의 커밋 후 데이터 손실 이벤트는 트랜잭션 관리자가 처리하지 않으며 RM의 복원 기능입니다.
2 단계 커밋은 내결함성을 보장하지 않습니다. 내결함성을 해결하는 프로토콜의 예는 Paxos 를 참조하세요. 하지만 분산 트랜잭션의 부분적 실패가 눈에 띄지 않도록 보장합니다.
- 이러한 종류의 실패는 이전에 커밋 된 트랜잭션에서 데이터를 잃을 수도 있습니다. 2 단계 커밋은 리소스 관리자가 데이터를 잃거나 손상시킬 수 없거나 DR 절차가 망가지지 않는다는 것을 보장하지 않습니다.
모든 노력에도 불구하고 상황이 궁극적으로 잘못 될 수있는 시나리오는 시나리오 만이 아닙니다. A와 B가 모두 TM에 "준비 완료"를보고 한 다음 누군가 TM과 B 사이의 경계를 뽑았다 고 가정합니다. TM이 다시 연결될 때까지 계속 기다리지 마십시오 (트랜잭션에 관련된 자체 리소스는 명백한 이유로 전체 대기 시간 동안 잠금 / 액세스 불가능 상태로 유지되어야 함). 따라서 B가 자신의 취향을 위해 너무 오래 기다리면 "휴리스틱 결정"이라고하는 것이 필요합니다. 즉, TM과는 독립적으로 커밋하거나 롤백하기로 결정할 것입니다. 글쎄요, 저는 실제로 무엇을 알지 못하지만 실제로는 중요하지 않습니다. 그러한 휴리스틱 결정은 TM이 취한 실제 커밋 결정과 다를 수 있음이 분명해야합니다.
3 단계 커밋이 훨씬 더 나은 방법이라고 생각합니다. 불행히도 나는 그러한 기술을 구현하는 사람을 찾지 못했습니다.
http://the-paper-trail.org/blog/consensus-protocols-three-phase-commit/
위 기사의 핵심 부분은 다음과 같습니다.
2PC의 근본적인 어려움은 코디네이터가 커밋 결정을 내리고 일부 복제본에 전달하면 복제본이 다른 모든 복제본이 메시지를 받았는지 확인하지 않고 바로 커밋 명령문에 따라 작동한다는 것입니다. 그런 다음 커밋 된 복제본이 코디네이터와 함께 충돌하면 시스템은 트랜잭션 결과가 무엇인지 알 수 없습니다 (코디네이터와 메시지를받은 복제본 만 확실히 알고 있기 때문입니다). 트랜잭션이 충돌 한 복제본에서 이미 커밋되었을 수 있으므로 프로토콜은 비관적으로 중단 할 수 없습니다. 트랜잭션에 실행 취소 할 수없는 부작용이있을 수 있기 때문입니다. 마찬가지로, 프로토콜은 원래 투표가 중단되었을 수 있으므로 트랜잭션을 낙관적으로 강제 할 수 없습니다.
이 문제는 – 대부분 – 2PC에 추가 단계를 추가하여 피할 수 있으며, 당연히 3 단계 커밋 프로토콜을 제공합니다. 아이디어는 매우 간단합니다. 2PC의 두 번째 단계 인 '커밋'을 두 개의 하위 단계로 나눕니다. 첫 번째는 '커밋 준비'단계입니다. 코디네이터는 첫 번째 단계에서 만장일치로 '예'투표를받은 경우 모든 복제본에이 메시지를 보냅니다. 이 메시지를 수신하면 복제본은 필요한 잠금 등을 사용하여 트랜잭션을 커밋 할 수있는 상태가되지만 결정적으로 나중에 실행 취소 할 수없는 작업을 수행하지 않습니다. 그런 다음 코디네이터에게 '커밋 준비'메시지를 받았다고 응답합니다.
이 단계의 목적은 모든 복제본에 투표 결과를 전달하여 어떤 복제본이 죽더라도 프로토콜의 상태를 복구 할 수 있도록하는 것입니다.
프로토콜의 마지막 단계는 2PC의 원래 '커밋 또는 중단'단계와 거의 똑같은 작업을 수행합니다. 코디네이터가 모든 복제본에서 '커밋 준비'메시지의 전달 확인을 받으면 트랜잭션 커밋을 진행하는 것이 안전합니다. 그러나 전달이 확인되지 않으면 코디네이터는 프로토콜 상태가 충돌 할 경우 복구 될 것이라고 보장 할 수 없습니다 (고정 된 수의 실패를 허용하는 경우 코디네이터는 f + 1을 수신하면 진행할 수 있습니다. 확인). 이 경우 코디네이터는 트랜잭션을 중단합니다.
If the co-ordinator should crash at any point, a recovery node can take over the transaction and query the state from any remaining replicas. If a replica that has committed the transaction has crashed, we know that every other replica has received a ‘prepare to commit’ message (otherwise the co-ordinator wouldn’t have moved to the commit phase), and therefore the recovery node will be able to determine that the transaction was able to be committed, and safely shepherd the protocol to its conclusion. If any replica reports to the recovery node that it has not received ‘prepare to commit’, the recovery node will know that the transaction has not been committed at any replica, and will therefore be able either to pessimistically abort or re-run the protocol from the beginning.
So does 3PC fix all our problems? Not quite, but it comes close. In the case of a network partition, the wheels rather come off – imagine that all the replicas that received ‘prepare to commit’ are on one side of the partition, and those that did not are on the other. Then both partitions will continue with recovery nodes that respectively commit or abort the transaction, and when the network merges the system will have an inconsistent state. So 3PC has potentially unsafe runs, as does 2PC, but will always make progress and therefore satisfies its liveness properties. The fact that 3PC will not block on single node failures makes it much more appealing for services where high availability is more important than low latencies.
ReferenceURL : https://stackoverflow.com/questions/7389382/two-phase-commit
'Program Club' 카테고리의 다른 글
| CDN (콘텐츠 전송 네트워크) 사용의 장단점은 무엇입니까? (0) | 2021.01.08 |
|---|---|
| VIM : 커서 / 화살표 키 비활성화 (탐색 전용) (0) | 2021.01.08 |
| Node.js의 "connect EMFILE"오류 (0) | 2021.01.08 |
| RESTful HTTP 대신 Websocket을 사용하면 어떤 함정이 있습니까? (0) | 2021.01.07 |
| memcpy를위한 향상된 REP MOVSB (0) | 2021.01.07 |