[마이크로서비스] 분산 트랜잭션 소개

1. 거래 소개

트랜잭션은 데이터베이스의 다양한 데이터 항목에 액세스하고 업데이트할 수 있는 프로그램 실행 단위입니다. 관계형 데이터베이스에서 트랜잭션은 일련의 SQL 문으로 구성됩니다. 트랜잭션에는 원자성, 일관성, 격리 및 내구성의 4가지 속성이 있어야 합니다. 이 네 가지 속성을 종종 ACID 속성이라고 합니다.

원자성( Atomicity ) : 트랜잭션은 나눌 수 없는 작업 단위이며 트랜잭션에 포함된 작업이 수행되거나 수행되지 않습니다.
일관성 : 트랜잭션은 데이터베이스가 일관성 있는 상태에서 다른 상태로 변경되고 트랜잭션의 중간 상태를 관찰할 수 없도록 해야 합니다.
격리( Isolation ) : 트랜잭션의 실행이 다른 트랜잭션의 간섭을 받을 수 없습니다. 즉, 트랜잭션 내의 작업과 사용되는 데이터가 다른 동시 트랜잭션과 격리되고 동시에 실행되는 트랜잭션이 서로 간섭할 수 없습니다. 격리는 커밋되지 않은 읽기( 커밋되지 않은 읽기), 커밋된 읽기( 커밋된 읽기, 더티 읽기 해결), 반복 가능한 읽기(반복 가능한 읽기, 가상 읽기 해결), 직렬화(직렬화 가능, 팬텀 읽기 해결)의 네 가지 수준으로 나뉩니다.
지속성 : 지속성이라고도 하는 지속성은 트랜잭션이 커밋되면 데이터베이스의 데이터에 대한 변경 사항이 영구적이어야 함을 의미합니다. 뒤따르는 다른 작업이나 오류는 영향을 미치지 않아야 합니다.
트랜잭션 메커니즘을 구현할 때 시간에 만족할 수 없는 로컬 트랜잭션 및 분산 트랜잭션을 포함하여 트랜잭션의 ACID 특성과 지원 정도를 고려해야 합니다.

2. 지역사정

대부분의 시나리오에서 애플리케이션은 단일 데이터베이스만 운영하면 되며 이 경우의 트랜잭션을 로컬 트랜잭션( Local Transaction)이라고 합니다. 로컬 트랜잭션의 ACID 기능은 데이터베이스가 직접 지원을 제공한다는 것입니다. 로컬 트랜잭션 애플리케이션 아키텍처는 다음과 같습니다.
여기에 이미지 설명 삽입

JDBC 프로그래밍에서는 java.sql.Connection객체를 사용하여 트랜잭션을 열거나 닫거나 커밋합니다. 코드는 다음과 같습니다.

Connection conn = ... //获取数据库连接
conn.setAutoCommit(false); //开启事务
try{
    
    
   //...执行增删改查sql
   conn.commit(); //提交事务
}catch (Exception e) {
    
    
  conn.rollback();//事务回滚
}finally{
    
    
   conn.close();//关闭链接
}

3. 분산 트랜잭션의 일반적인 시나리오

현재 인터넷의 발달은 한창이며 대부분의 기업은 데이터베이스 분할 및 서비스 지향(SOA)을 수행하고 있습니다. 이 경우 비즈니스 기능을 완료하려면 여러 서비스에 걸쳐 있고 여러 데이터베이스를 운영해야 할 수 있습니다. 여기에는 분산 트랜잭션이 포함되며, 운영해야 하는 리소스는 여러 리소스 서버에 있으며 애플리케이션은 여러 리소스 서버의 데이터에 대한 작업이 모두 성공하거나 모두 실패하는지 확인해야 합니다. 본질적으로 분산 트랜잭션은 서로 다른 리소스 서버 간의 데이터 일관성을 보장하기 위한 것입니다.
일반적인 분산 트랜잭션 시나리오:

3.1) 데이터베이스 간 거래

데이터베이스 간 트랜잭션은 응용 프로그램의 특정 기능이 여러 라이브러리를 운영해야 하고 서로 다른 라이브러리가 서로 다른 비즈니스 데이터를 저장해야 함을 의미합니다. 저자는 9개의 도서관이 동시에 운영되는 비교적 복잡한 비즈니스를 보았습니다. 다음 그림은 동시에 2개의 라이브러리를 운영하는 서비스를 보여줍니다.
여기에 이미지 설명 삽입

3.2) 서브 라이브러리 및 서브 테이블

일반적으로 많은 양의 데이터가 있거나 미래에 예상되는 대량의 데이터가 있는 데이터베이스는 수평으로 분할됩니다. 즉, 하위 데이터베이스와 하위 테이블입니다. 아래 그림과 같이 데이터베이스 B는 2개의 라이브러리로 분할됩니다.
여기에 이미지 설명 삽입

하위 데이터베이스 및 하위 테이블의 경우 일반 개발자는 일부 데이터베이스 미들웨어를 사용하여 SQL 작업의 복잡성을 줄입니다. 예를 들어 sql의 경우: 사용자(id, name) 값(1, "Zhang San"), (2, "Li Si")에 삽입합니다. 이 sql은 단일 데이터베이스를 운용하기 위한 구문으로 단일 데이터베이스의 경우 트랜잭션 일관성을 보장할 수 있다.

그러나 이제 하위 데이터베이스와 하위 테이블이 수행되었으므로 개발자는 하위 데이터베이스 1에 1번 레코드를 삽입하고 하위 데이터베이스 2에 2번 레코드를 삽입하기를 희망합니다. 따라서 데이터베이스 미들웨어는 이를 두 개의 sql에 다시 작성하여 두 개의 서로 다른 하위 데이터베이스에 삽입해야 합니다. 이때 두 데이터베이스가 모두 성공하거나 실패하는지 확인해야 합니다. 따라서 기본적으로 모든 데이터베이스 미들웨어는 분산 트랜잭션 문제에 직면하게 됩니다. .

3.3) 서비스

마이크로서비스 아키텍처는 현재 비교적 대중적인 개념입니다. 예를 들어 위의 저자가 언급한 경우 응용 프로그램은 동시에 9개의 라이브러리를 작동합니다. 이러한 응용 프로그램의 비즈니스 논리는 매우 복잡해야 개발자에게 큰 도전입니다. 다른 독립적인 서비스로 분할되어야 합니다. 비즈니스 로직을 단순화하기 위해.. 분할 후 독립 서비스는 RPC 프레임워크를 사용하여 원격 호출을 통해 서로 통신합니다. 다음 다이어그램은 3개의 서비스가 서로를 호출하는 아키텍처를 보여줍니다.
여기에 이미지 설명 삽입

서비스 A는 특정 기능을 완료하기 위해 데이터베이스를 직접 운영해야 하며 서비스 B와 서비스 C를 동시에 호출해야 하고 서비스 B는 동시에 두 개의 데이터베이스를 운영하고 서비스 C도 라이브러리를 운영해야 한다. 여러 데이터베이스에서 이러한 교차 서비스 작업이 성공하거나 실패하는지 확인하는 것이 필요하며 실제로 이것이 가장 일반적인 분산 트랜잭션 시나리오일 수 있습니다.

요약: 위에서 설명한 분산 트랜잭션 시나리오에서는 예외 없이 여러 데이터베이스가 직간접적으로 운영됩니다. 트랜잭션의 ACID 특성을 보장하는 방법은 분산 트랜잭션 구현 솔루션에 있어 매우 큰 과제입니다. 동시에 분산 트랜잭션 구현 방식은 성능 문제도 고려해야 하며 ACID 특성을 엄격하게 보장하기 위해 성능이 심각하게 저하되는 경우 빠른 응답이 필요한 일부 서비스에 대해 허용되지 않습니다.

4. X/Open DTP 모델 및 XA 사양

이제 공개 그룹이 된 X/Open은 다양한 산업 기술 표준을 공식화하는 일을 주로 담당하는 독립 조직입니다. DTP(Distributed Transaction Processing)에 관한 한 X/Open은 주로 다음 참조 문서를 제공합니다.
DTP 참조 모델: 분산 트랜잭션 처리: 참조 모델
DTP XA 사양: 분산 트랜잭션 처리: XA 사양

4.1 DTP 모델

DTP 모델을 구성하는 5가지 기본 요소:
응용 프로그램(줄여서 AP) : 트랜잭션 경계를 정의(즉, 트랜잭션의 시작과 끝을 정의)하고 트랜잭션 경계 내의 리소스에 대해 작동하는 데 사용됩니다.
Resource Manager(Resource Manager, RM이라고 함) : 데이터베이스, 파일 시스템 등으로 리소스에 접근할 수 있는 방법을 제공합니다.
트랜잭션 관리자(Transaction Manager, TM) : 트랜잭션의 고유 식별자 할당, 트랜잭션 실행 진행 모니터링, 트랜잭션 제출 및 롤백을 담당합니다.
Communication Resource Manager(줄여서 CRM) : TM 도메인(TM 도메인) 내 또는 TM 도메인 전반에 걸쳐 분산 애플리케이션 간의 통신을 제어합니다.
Communication Protocol(약칭 CP) : CRM에서 제공하는 분산 응용 프로그램 노드 간의 기본 통신 서비스를 제공합니다.

4.2 XA 사양

 在DTP本地模型实例中,由AP、RMs和TM组成,不需要其他元素。AP、RM和TM之间,彼此都需要进行交互,如下图所示: 

여기에 이미지 설명 삽입

이 그림에서 (1)은 AP-RM의 인터랙션 인터페이스, (2)는 AP-TM의 인터랙션 인터페이스, (3)은 RM-TM의 인터랙션 인터페이스를 나타낸다.

XA 사양의 주요 기능은 RM-TM 상호 작용 인터페이스를 정의하는 것이며, 정의된 RM-TM 상호 작용 인터페이스(XA Interface) 외에도 XA 사양은 2단계 커밋 프로토콜을 최적화합니다.

OSI TP 표준에서는 2단계 커밋 프로토콜을 제안하고, DTP 참조 모델(<>)에서는 글로벌 트랜잭션 제출을 위해 2단계 커밋 프로토콜을 지정하고, XA 사양(<< 분산 트랜잭션 처리: XA 사양 >>) 2단계 커밋 프로세스의 참여자는 TM 및 RM.

5. 2단계 커밋 프로토콜(2PC)

Two Phase Commit(Two Phase Commit)은 XA 사양에서 제안하지 않지만 XA 사양에서 이를 최적화합니다. 문자 그대로의 의미에서 Two Phase Commit은 커밋 프로세스를 두 단계(Phase)로 나누는 것입니다.
Phase 1:
TM은 각 RM에게 트랜잭션 분기 커밋을 준비하도록 알립니다. RM이 수행한 작업을 제출할 수 있다고 판단하면 작업 내용을 유지하고 TM에 긍정적인 답변을 제공하고 다른 상황이 발생하면 TM에 부정적인 답변을 제공합니다. 부정적인 응답을 보내고 이미 완료된 작업을 롤백한 후 RM은 트랜잭션 분기 정보를 삭제할 수 있습니다.

mysql 데이터베이스를 예로 들면, 첫 번째 단계에서 트랜잭션 관리자는 관련된 모든 데이터베이스 서버에 준비 "제출 준비" 요청을 보냅니다. 데이터베이스는 요청을 받은 후 데이터 수정 및 로깅 처리를 수행합니다. 처리 후 완료되면 트랜잭션만 저장하고 상태는 "Committable"로 변경되고 결과는 트랜잭션 관리자에게 반환됩니다.

Phase 2
TM은 Phase 1에서 준비한 각 RM의 결과에 따라 트랜잭션을 커밋할지 롤백할지 결정합니다. 모든 RM이 성공적으로 준비되면 TM은 모든 RM에게 커밋하도록 알리고, RM 준비가 실패하면 모든 RM에게 트랜잭션 분기를 롤백하도록 알립니다.
mysql 데이터베이스를 예로 들면 첫 번째 단계에서 모든 데이터베이스가 성공적으로 준비되면 트랜잭션 관리자는 데이터베이스 서버에 "커밋 확인" 요청을 보내고 데이터베이스 서버는 트랜잭션의 "커밋 가능" 상태를 " 커밋 완료" 상태를 확인한 다음 답변을 반환합니다. 첫 번째 단계의 데이터베이스 작업에 오류가 있거나 트랜잭션 관리자가 데이터베이스로부터 응답을 받지 못하면 트랜잭션이 실패한 것으로 간주되고 모든 데이터베이스 트랜잭션이 롤백됩니다. 데이터베이스 서버는 두 번째 단계에서 확인 커밋 요청을 수신하지 않으며 "커밋 가능한" 트랜잭션도 철회합니다.
여기에 이미지 설명 삽입
여기에 이미지 설명 삽입

XA는 강력한 일관성을 가진 리소스 수준의 분산 트랜잭션으로 2단계 커밋의 전체 프로세스 동안 리소스 잠금이 항상 유지됩니다.
TCC는 최종 일관성이 있는 비즈니스 수준의 분산 트랜잭션이며 항상 리소스 잠금을 유지하지 않습니다.
TCC에 대한 자세한 내용은 다음 문서를 참조하십시오. 유연한 거래: TCC 2단계 보상 유형

2PC(Two-Phase Commit Protocol)의 문제
2단계 커밋은 원자적 작업을 제공할 수 있는 것처럼 보이지만 불행히도 2단계 커밋에는 여전히 몇 가지 단점이 있습니다.
1. 동기식 차단 문제.
2단계 커밋 체계에서 전역 트랜잭션의 ACID 속성은 RM에 따라 다릅니다. 글로벌 트랜잭션에는 여러 개의 독립적인 트랜잭션 분기가 포함되며 이 트랜잭션 분기 그룹은 성공하거나 실패합니다. 각 트랜잭션 분기의 ACID 속성은 함께 글로벌 트랜잭션의 ACID 속성을 구성합니다. 즉, 단일 트랜잭션 분기에서 지원하는 ACID 기능이 분산 트랜잭션 범주로 업그레이드됩니다. 로컬 트랜잭션에서도 작동 읽기에 민감한 경우 트랜잭션 격리 수준을 SERIALIZABLE로 설정해야 합니다. 이는 특히 반복 가능한 읽기 격리 수준이 분산 트랜잭션 일관성을 보장하기에 충분하지 않은 분산 트랜잭션에 해당됩니다. mysql을 사용하여 XA 분산 트랜잭션을 지원한다면 트랜잭션 격리 수준을 SERIALIZABLE로 설정하는 것이 가장 좋지만 SERIALIZABLE(직렬화)은 4가지 트랜잭션 격리 수준 중 가장 높은 수준이고 실행 효율성은 가장 낮은 수준입니다.
2. 단일 실패 지점.
코디네이터의 중요성으로 인해 코디네이터 TM이 실패하면 참가자 RM은 항상 차단됩니다. 특히 2단계에서 코디네이터가 실패하면 모든 참여자는 여전히 트랜잭션 자원을 잠그고 있는 상태로 계속해서 트랜잭션 작업을 완료할 수 없습니다. (코디네이터가 다운된 경우, 코디네이터를 재선출할 수 있지만, 코디네이터의 다운타임으로 인해 참가자가 차단되는 문제는 해결할 수 없습니다.)
3. 데이터 불일치.
2단계 제출의 두 번째 단계에서는 코디네이터가 참가자에게 커밋 요청을 보낸 후 로컬 네트워크 예외가 발생하거나 커밋 요청을 보내는 과정에서 코디네이터가 실패하여 참가자 중 일부만 이 부분의 참여자가 커밋 요청을 받은 후 커밋 작업을 수행하지만 커밋 요청을 수신하지 않은 다른 시스템은 트랜잭션 커밋을 수행할 수 없습니다. 결과적으로 전체 분산 시스템에서 데이터 불일치가 발생합니다.

2단계 커밋은 동기 블로킹, 단일점 문제 등의 결함이 있기 때문에 연구원들은 2단계 커밋을 기반으로 개선하고 3단계 커밋을 제안했다.

6. 3단계 커밋

3단계 커밋(3PC)은 2단계 커밋(2PC)의 개선된 버전입니다.
2단계 커밋과 달리 3단계 커밋에는 두 가지 변경점이 있습니다.

1. 타임아웃 메커니즘을 도입합니다. 동시에 조정자와 참가자 모두에게 타임아웃 메커니즘이 도입됩니다.
2. 첫 번째 단계와 두 번째 단계 사이에 준비 단계를 삽입합니다. 각 참여 노드의 상태는 최종 커밋 단계 전에 일관성이 보장됩니다.
즉, 타임아웃 메커니즘 도입과 함께 3PC는 2PC의 준비 단계를 다시 2개로 나누어 3단계 제출이 CanCommit, PreCommit, DoCommit의 3단계로 구성된다.
여기에 이미지 설명 삽입

캔커밋 단계

3PC의 CanCommit 단계는 실제로 2PC의 준비 단계와 매우 유사합니다. 코디네이터는 참가자에게 커밋 요청을 보내고 참가자가 제출할 수 있으면 참가자는 예 응답을 반환하고 그렇지 않으면 아니요 응답을 반환합니다.
1. 트랜잭션은 조정자에게 참가자에게 CanCommit 요청을 보내도록 요청합니다. 트랜잭션 커밋 작업을 수행할 수 있는지 묻습니다. 그런 다음 참가자의 응답을 기다리기 시작합니다.
2. 응답 피드백 참가자가 CanCommit 요청을 받은 후 정상적인 상황에서 트랜잭션이 원활하게 실행될 수 있다고 판단되면 Yes 응답을 반환하고 준비 상태로 들어갑니다. 그렇지 않으면 피드백 아니요

사전 커밋 단계

코디네이터는 참여자의 반응에 따라 트랜잭션의 PreCommit 동작을 기억할 수 있는지 여부를 결정합니다. 응답에 따라 다음 두 가지 가능성이 있습니다.
코디네이터가 모든 참가자로부터 Yes 응답을 받으면 트랜잭션의 사전 실행이 수행됩니다.
1. 사전 커밋 요청 보내기 코디네이터는 참가자에게 사전 커밋 요청을 보내고 준비 단계에 들어갑니다.
2. 트랜잭션 사전 커밋 참가자는 사전 커밋 요청을 수신한 후 트랜잭션 작업을 실행하고 트랜잭션 로그에 실행 취소 및 다시 실행 정보를 기록합니다.
3. 응답 피드백 참가자가 트랜잭션 작업을 성공적으로 수행하면 ACK 응답을 반환하고 최종 명령을 기다리기 시작합니다.
참가자가 코디네이터에게 No 응답을 보내거나 타임아웃을 기다린 후 코디네이터가 참가자로부터 응답을 받지 못하면 트랜잭션이 중단됩니다.
1. 인터럽트 요청 보내기 코디네이터는 모든 참가자에게 중단 요청을 보냅니다.
2. Interrupt transaction 참가자가 조정자로부터 중단 요청을 받은 후(또는 타임아웃 후에 조정자의 요청이 수신되지 않은 경우) 트랜잭션이 중단됩니다.

doCommit 단계

이 단계는 실제 트랜잭션 제출을 수행하며 다음 두 가지 상황으로 나눌 수도 있습니다.
사례 1: 커밋 실행
1. 커밋 요청을 보내고 참가자가 보낸 ACK 응답을 조정하고 수신하면 커밋 전 상태에서 커밋 상태로 들어갑니다. 모든 참가자에게 doCommit 요청을 보냅니다.
2. 트랜잭션 제출 참가자가 doCommit 요청을 받은 후 공식적인 트랜잭션 제출이 수행됩니다. 그리고 트랜잭션 커밋이 완료된 후 모든 트랜잭션 리소스를 해제합니다.
3. 응답 피드백 트랜잭션이 제출된 후 코디네이터에게 Ack 응답을 보냅니다.
4. 트랜잭션 코디네이터가 모든 참가자로부터 ack 응답을 받은 후 트랜잭션이 완료됩니다.
사례 2: 인터럽트 트랜잭션 조정자는 참가자가 보낸 ACK 응답을 수신하지 않으면(수신자가 응답 이외의 ACK 응답을 보냈거나 응답 시간이 초과되었을 수 있음) 인터럽트 트랜잭션이 실행됩니다.
1. 인터럽트 요청 보내기 코디네이터가 모든 참가자에게 중단 요청을 보냅니다.
2. 트랜잭션 롤백 중단 요청을 받은 참가자는 2단계에서 기록된 실행 취소 정보를 사용하여 트랜잭션 롤백 작업을 수행하고, 롤백이 완료된 후 모든 트랜잭션을 해제합니다. 자원.
3. 피드백 결과 참가자가 트랜잭션 롤백을 완료한 후 ACK 메시지를 코디네이터에게 전송
4. 트랜잭션 중단 코디네이터는 참가자가 피드백한 ACK 메시지를 받은 후 트랜잭션을 중단합니다.

doCommit 단계에서 참가자가 코디네이터로부터 doCommit 또는 rebort 요청을 제때 받지 못하면 타임아웃을 기다린 후 트랜잭션을 계속 커밋합니다. (실제로는 확률에 따라 결정해야 합니다. 3단계 진입 시 참여자가 2단계에서 PreCommit 요청을 받았다는 의미이므로, 코디네이터가 PreCommit 요청을 받기 위한 전제 조건은 PreCommit 요청을 받는 것입니다. 모든 참가자에 대한 CanCommit 응답은 Yes입니다.(참가자가 PreCommit을 수신하면 모든 사람이 수정 사항에 동의한다는 것을 알고 있음을 의미합니다.) 따라서 한 문장으로 세 번째 단계에 들어갈 때, 네트워크 시간 초과 및 기타 이유로 참가자가 커밋 또는 중단 응답을 받지 못했지만 성공적인 커밋의 가능성이 높다고 믿을 만한 이유가 있었습니다.)

2PC와 3PC의 차이점

2PC에 비해 3PC는 주로 단일 실패 지점 문제를 해결하고 차단을 줄입니다. 참가자가 제 시간에 코디네이터로부터 정보를 받지 못하면 기본적으로 커밋을 실행하기 때문입니다. 트랜잭션 리소스를 항상 보유하고 차단하는 대신. 그러나 이 메커니즘은 네트워크 문제로 인해 조정자가 보낸 중단 응답을 참가자가 제때 받지 못하고 참가자가 시간 초과를 기다린 후 커밋 작업을 수행하기 때문에 데이터 일관성 문제도 발생합니다. 이런 식으로 중단 명령을 받고 롤백을 수행하는 다른 참가자 간에 데이터 불일치가 발생합니다.

2PC와 3PC를 이해하면 2단계 커밋이나 3단계 커밋 모두 분산 일관성 문제를 완전히 해결할 수 없음을 알 수 있습니다. 따라서 분산 시나리오에서는 종종 99.9% 또는 99.99%만 보장할 수 있다고 말할 수 있습니다. 이러한 데이터 일관성.

추천

출처blog.csdn.net/haohaoxuexiyai/article/details/123744746