비즈니스의 급속한 발전과 비즈니스의 복잡성 증가로 인해 거의 모든 회사의 시스템은 모놀리식에서 분산형으로, 특히 마이크로서비스 아키텍처로 전환할 것입니다. 그러면 필연적으로 분산 트랜잭션 문제에 직면하게 됩니다.
이 기사에서는 먼저 관련 기본 이론을 소개한 다음 가장 고전적인 트랜잭션 솔루션을 요약하고 마지막으로 모두가 공유하는 하위 트랜잭션의 비순차적 실행(멱등성, 널 보상 및 정지 문제)에 대한 솔루션을 제공합니다. .
기본 이론
구체적인 솔루션을 설명하기 전에 먼저 분산 트랜잭션과 관련된 기본 이론적 지식을 이해하겠습니다.
이체를 예로 들어 보겠습니다. A는 B에게 100위안을 이체해야 하며, A의 잔액은 -100위안이어야 하고, B의 잔액은 +100위안이어야 합니다. 전체 이체는 A-100과 B를 보장해야 합니다. +100이 동시에 성공하거나 둘 다 실패했습니다. 다양한 시나리오에서 이 문제가 어떻게 해결되는지 살펴보겠습니다.
Transaction
여러 문을 전체적으로 운영하는 기능을 데이터베이스 트랜잭션이라고 합니다. 데이터베이스 트랜잭션은 트랜잭션 범위 내의 모든 작업이 성공하거나 실패할 수 있도록 보장합니다.
트랜잭션에는 원자성, 일관성, 격리성, 내구성이라는 4가지 속성이 있습니다. 이러한 네 가지 속성을 흔히 ACID 속성이라고 합니다.
- Atomicity(원자성): 트랜잭션의 모든 작업은 완전히 완료되거나 완료되지 않으며 중간 링크로 끝나지 않습니다. 트랜잭션 실행 중 오류가 발생하면 트랜잭션이 한 번도 실행되지 않았던 것처럼 트랜잭션이 시작되기 전의 상태로 복원됩니다.
- 일관성: 트랜잭션이 시작되기 전과 트랜잭션이 끝난 후에도 데이터베이스의 무결성이 손상되지 않습니다. 외래 키 제약 조건, 애플리케이션 정의 제약 조건 등을 포함한 무결성은 파괴되지 않습니다.
- 격리: 데이터베이스를 사용하면 여러 동시 트랜잭션이 동시에 데이터를 읽고 쓰고 수정할 수 있습니다. 격리를 사용하면 여러 트랜잭션이 동시에 실행될 때 교차 실행으로 인한 데이터 불일치를 방지할 수 있습니다.
- 내구성: 거래가 완료된 후 데이터 수정 사항은 영구적이며 시스템 오류가 발생하더라도 손실되지 않습니다.
저희 비즈니스 시스템이 복잡하지 않고 하나의 데이터베이스와 하나의 서비스에서 데이터를 수정하고 전송을 완료할 수 있다면 데이터베이스 트랜잭션을 사용하여 전송 비즈니스를 올바르게 완료할 수 있습니다.
분산 거래
은행간 이체 사업은 A가 은행을 거쳐 B에게 돈을 이체해야 하는데, 두 은행의 데이터가 포함되어 있어 현지 거래를 통해 이체의 ACID를 보장할 수 없는 전형적인 분산 거래 시나리오입니다. 데이터베이스는 분산 트랜잭션을 통해 해결됩니다.
분산 트랜잭션은 트랜잭션 개시자, 리소스 및 리소스 관리자, 트랜잭션 코디네이터가 분산 시스템의 서로 다른 노드에 위치한다는 것을 의미합니다. 위의 전송사업에서는 사용자 A-100의 동작과 사용자 B+100의 동작이 동일한 노드에 위치하지 않습니다. 기본적으로 분산 트랜잭션은 분산 시나리오에서 데이터 작업이 올바르게 실행되도록 보장합니다.
분산 환경의 분산 트랜잭션은 가용성, 성능 및 다운그레이드된 서비스 요구 사항을 충족하고 일관성 및 격리에 대한 요구 사항을 줄이기 위해 한편으로는 BASE 이론(BASE 관련 이론, 많은 내용이 포함됨)을 따릅니다. 내용, 관심 있는 학생은 BASE 이론을 참조할 수 있습니다):
- 기본 비즈니스 가용성(Basic Availability)
- 소프트 상태(Soft state)
- 최종 일관성(Eventual Consistency)
마찬가지로 분산 트랜잭션도 부분적으로 다음을 따릅니다. ACID 사양:
- 원자성: 엄격하게 준수됨
- 일관성: 트랜잭션 완료 후 일관성을 엄격하게 준수함, 트랜잭션 내 일관성을 적절하게 완화할 수 있음
- 격리성: 병렬 트랜잭션에 영향을 줄 수 없음 중간 트랜잭션 결과의 가시성을 보장함
- 내구성:
분산 트랜잭션 솔루션
을 엄격히 준수합니다. 분산 트랜잭션 솔루션으로 인해 완전한 ACID 보장을 달성할 수 없으며 모든 비즈니스 문제를 해결할 수 있는 완벽한 솔루션도 없습니다. 따라서 실제 애플리케이션에서는 비즈니스의 다양한 특성에 따라 가장 적합한 분산 트랜잭션 솔루션이 선택됩니다.
Two-phase commit/XA
XA는 X/Open 조직에서 제안한 분산 트랜잭션 사양입니다. XA 사양은 주로 (글로벌) 트랜잭션 관리자(TM)와 (로컬) 리소스 관리자(RM) 간의 관계를 정의합니다. ) 인터페이스. mysql과 같은 로컬 데이터베이스는 XA에서 RM의 역할을 합니다
XA는 두 단계로 나누어집니다.
첫 번째 단계(준비): 즉, 모든 참가자 RM은 트랜잭션을 실행하고 필요한 리소스를 잠글 준비를 합니다. 참가자가 준비되면 TM에 준비되었음을 보고합니다.
2단계(커밋/롤백): 트랜잭션 관리자(TM)가 모든 참가자(RM)가 준비되었음을 확인하면 모든 참가자에게 커밋 명령을 보냅니다.
현재 주류 데이터베이스는 기본적으로 mysql, oracle, sqlserver, postgre를 포함한 XA 트랜잭션을 지원합니다.
XA 트랜잭션은 하나 이상의 리소스 관리자(RM), 트랜잭션 관리자(TM) 및 애플리케이션(ApplicationProgram)으로 구성됩니다.
여기서 RM, TM, AP의 세 가지 역할은 고전적인 역할 구분으로, 후속 Saga, Tcc 및 기타 거래 모드 전반에 걸쳐 사용됩니다.
위의 전송을 예로 들어 보겠습니다. 성공적으로 완료된 XA 트랜잭션 순서 다이어그램은 다음과 같습니다.
참가자가 준비에 실패하면 TM은 준비를 완료한 모든 참가자에게 롤백을 알립니다.
XA 트랜잭션의 특징은 다음과 같습니다.
- 간단하고 이해하기 쉽고 개발하기 쉽습니다.
- 리소스의 장기 잠금, 낮은 동시성
독자가 XA를 더 배우고 싶다면 언어, PHP, Python, Java, C#, Node 등은 DTM
SAGA
을 참조할 수 있습니다. Saga는 이 데이터베이스 문서에서 sagas가 언급한 솔루션입니다. 핵심 아이디어는 Saga 트랜잭션 코디네이터가 조정하여 긴 트랜잭션을 여러 로컬 짧은 트랜잭션으로 분할하는 것입니다. 정상적으로 종료되면 단계가 실패하면 보상 작업이 역순으로 한 번 호출됩니다.
위의 전송을 예로 들면, 성공적으로 완료된 SAGA 트랜잭션 시퀀스 다이어그램은 다음과 같습니다.
Saga가 취소 단계에 도달하면 비즈니스 로직에서 취소가 실패하는 것이 허용되지 않습니다. 네트워크 또는 기타 일시적인 오류로 인해 성공이 반환되지 않으면 TM은 취소가 성공을 반환할 때까지 계속 재시도합니다.
Saga 트랜잭션의 특징:
- 높은 동시성, XA 트랜잭션처럼 오랫동안 리소스를 잠글 필요가 없음
- 정상 작업 및 보상 작업을 정의해야 하며 XA보다 개발 볼륨이 큼
- 일관성이 약함 이체, A가 발생할 수 있습니다. 사용자가 돈을 공제했고 최종 이체가 다시 실패했습니다
지점 거래의 동시 실행을 포함하여 두 가지 복구 전략을 포함하여 논문에 SAGA 내용이 많이 있습니다. 여기서 논의하는 것은 가장 간단한 것뿐입니다. SAGA
SAGA 적용 가능 시나리오가 많아 장기 거래에 적합하며, 중간 결과에 민감하지 않은 비즈니스 시나리오에 적합합니다
독자가 SAGA를 더 자세히 연구하고 싶다면 DTM을 참고하면 됩니다. SAGA 성공 및 실패 롤백 사례와 다양한 네트워크 이상 처리 사례가 포함되어 있습니다.
TCC
TCC(Try-Confirm-Cancel) 개념은 Pat Helland가 2007년에 발표한 "Life Beyond Distributed Transactions: an Apostate's Opinion"이라는 제목의 논문에서 처음 제안되었습니다.
TCC는 3단계로 나누어집니다
- 시도 단계: 실행 시도, 모든 업무 점검 완료(일관성), 필요한 업무 자원 확보(준격리)
- 확인 단계: 실행이 실제 업무 실행인지 확인, 비즈니스가 수행되지 않습니다. 시도 단계에서 예약된 비즈니스 리소스만 사용되는지 확인하세요. 확인 작업에는 멱등성 디자인이 필요합니다. 확인이 실패한 후 다시 시도해야 합니다.
- Cancel 단계: 실행을 취소하고 Try 단계에서 예약된 비즈니스 리소스를 해제합니다. 취소 단계의 예외 처리 방식은 기본적으로 확인 단계와 동일하며 멱등성 설계가 필요합니다.
위의 이체를 예로 들어보겠습니다. 일반적으로 Try에서는 금액이 동결되지만, 확정에서는 금액이 차감되고, 취소에서는 금액이 동결 해제됩니다.
TCC 확인/취소 단계의 비즈니스 로직은 실패 반환을 허용하지 않습니다. 네트워크 또는 기타 일시적인 오류로 인해 성공을 반환할 수 없는 경우 TM은 확인/취소가 성공을 반환할 때까지 계속 재시도합니다.
TCC 기능은 다음과 같습니다:
- 높은 동시성 및 장기 리소스 잠금이 없습니다.
- 개발량이 많아 Try/Confirm/Cancel 인터페이스를 제공해야 합니다.
- 일관성이 좋아졌고, SAGA가 돈을 차감한 후 송금에 실패한 상황이 발생하지 않습니다.
- TCC는 주문형 비즈니스, 중간 상태에 제약이 있는 비즈니스에 적합합니다. TCC에 대해 더 자세히 알아보려면 DTM을 참조하세요.
로컬 메시지와 비즈니스 운영을 하나의 트랜잭션에 넣으면 비즈니스와 메시지 전송의 원자성이 보장됩니다. 모두 성공하거나 모두 실패합니다.
내결함성 메커니즘:잔액 공제 트랜잭션이 실패하면 후속 단계 없이 트랜잭션이 직접 롤백됩니다.
- 휠 시퀀스 생성 메시지가 실패하면 잔액 증가 트랜잭션이 실패하면 재시도됩니다
- 로컬 메시지 테이블의 특징:
긴 트랜잭션은 여러 작업으로 분할하면 사용이 쉽습니다.
- 생산자는 추가 메시지 테이블을 생성해야 합니다.
- 각 로컬 메시지 테이블을 폴링해야 합니다
- 소비자가 로직이 재시도를 통해 성공하지 못하면 작업을 롤백하기 위해 더 많은 메커니즘이 필요합니다
- 비동기적으로 실행할 수 있고 후속 작업에 롤백이 필요하지 않은 비즈니스에 적용 가능
- 메시지 보내기(반 메시지)
- 서버는 메시지를 저장하고 메시지 쓰기 결과에 응답합니다.
- 전송 결과에 따라 로컬 트랜잭션을 실행합니다(쓰기가 실패할 경우, 절반 메시지는 비즈니스가 보이지 않고 로컬 로직이 실행되지 않음)
- 로컬 트랜잭션 상태에 따라 커밋 또는 롤백을 실행합니다. (커밋 작업은 메시지를 게시하고 메시지는 소비자에게 표시됩니다.)
- 소비자 로직이 재시도를 통과하지 못하면 롤백을 위해 더 많은 메커니즘이 필요합니다. 작업
- 비동기적으로 실행할 수 있고 후속 작업에 롤백이 필요하지 않은 비즈니스에 적용 가능
- 메시지 대기열 ACK 메커니즘, 메시지 대기열은 간격을 기반으로 합니다. 1분, 5분, 10분, 30분, 1시간, 2시간, 5시간, 10시간으로 설정하고 알림에 필요한 시간 창의 상한에 도달할 때까지 알림 간격을 점차 늘립니다. 이후에는 더 이상 알림이 없습니다
- 최선 알림은 비즈니스 알림 유형에 적합합니다. 예를 들어 WeChat 거래 결과는 최선 알림을 통해 각 판매자에게 통보됩니다.
- 비즈니스 처리 요청 4의 경우 Try 전에 취소가 실행되고 빈 롤백을 처리해야 하는 경우
- 비즈니스 요청 6을 처리하는 경우 , Cancel이 반복적으로 실행되며 멱등성이 있어야 합니다
- 비즈니스 처리 요청 8이 실행될 때 Cancel 이후에 Try가 실행되고 정지 처리가 필요합니다
Transaction Message
위의 로컬 메시지 테이블 솔루션에서 생산자는 추가 메시지 테이블을 생성하고 로컬 메시지 테이블을 폴링해야 하므로 비즈니스 부담이 큽니다. Alibaba의 오픈 소스 RocketMQ 4.3 이상에서는 트랜잭션 메시지를 공식적으로 지원합니다. 이 트랜잭션 메시지는 기본적으로 프로덕션 측에서 메시지 전송 및 로컬 트랜잭션 실행의 원자성 문제를 해결하기 위해 RocketMQ에 로컬 메시지 테이블을 배치합니다.
트랜잭션 메시지 전송 및 제출:
의 흐름도 일반적인 전송 방법은 다음과 같습니다.
보상 프로세스:
커밋/롤백이 없는 거래 메시지(보류 상태의 메시지)의 경우 서버에서 "검토"를 시작합니다.
Producer는 검토 메시지를 수신하고 거래 상태를 반환합니다. 커밋 또는 롤백인 메시지에 해당하는 로컬 트랜잭션
트랜잭션 메시지 솔루션 로컬 메시지 테이블 메커니즘과 매우 유사하지만 주요 차이점은 원래 관련 로컬 테이블 작업이 역방향 쿼리 인터페이스로 대체된다는 것입니다.
트랜잭션 메시지를 더 자세히 연구하고 싶은 독자는 DTM 또는 Rocketmq
Best Effort 알림
시작 알림 파티를 참조할 수 있습니다. 특정 메커니즘을 사용하여 비즈니스 처리 결과를 수신자에게 알리기 위해 최선을 다합니다. 구체적으로 다음을 포함합니다:
특정 메시지 반복 알림 메커니즘이 있습니다. 알림을 받는 당사자는 알림을 받지 못할 수 있으므로 메시지를 반복적으로 알리려면 특정 메커니즘이 마련되어 있어야 합니다.
메시지 교정 메커니즘. 최선의 노력에도 불구하고 수신자가 알림을 받지 못하거나 수신자가 메시지를 소비한 후 다시 소비하려는 경우 수신자는 요청을 충족하기 위해 알림자에게 메시지 정보를 적극적으로 쿼리할 수 있습니다.앞서 소개한 로컬 메시지 테이블과 트랜잭션 메시지는 모두 신뢰할 수 있는 메시지입니다. 여기서 소개한 최선의 알림과는 어떻게 다른가요?
신뢰할 수 있는 메시지 일관성. 시작 알림 당사자는 메시지가 전송되고 수신 알림 당사자에게 전송되는지 확인해야 합니다. 메시지 신뢰성의 핵심은 시작 알림 당사자에 의해 보장됩니다.
최선의 알림, 개시자는 수신 알림 당사자에게 업무 처리 결과를 알리기 위해 최선을 다하지만, 이때 메시지가 수신되지 않을 수 있습니다. 이때 수신 알림 당사자는 개시 알림의 인터페이스를 적극적으로 호출해야 합니다. 당사자가 업무 처리 결과를 조회하고, 통지를 받는 경우 신뢰성의 핵심은 통지를 받는 당사자입니다.
솔루션 측면에서 최선의 알림 요구 사항:
알림 수신자가 인터페이스를 통해 비즈니스 처리 결과를 쿼리할 수 있도록 인터페이스를 제공합니다.AT 거래 모드
Alibaba의 오픈소스 프로젝트인 Seata의 거래 모델입니다. Ant Financial에서는 FMT라고도 합니다. 트랜잭션 모드는 XA 모드와 유사하게 사용된다는 점과 비즈니스에서 다양한 보상 작업을 작성할 필요가 없으며 프레임워크에 의해 롤백이 자동으로 완료된다는 단점도 있습니다. - 높은 동시성 시나리오를 충족하지 못하는 용어 잠금. 성능 측면에서 AT 모드는 XA보다 높지만 더티 롤백과 같은 새로운 문제도 발생합니다. 관심 있는 학생들은 Seata-AT
예외 처리
를 참조하세요. 분산 트랜잭션의 모든 측면에서 네트워크 및 비즈니스 실패와 같은 문제가 발생할 수 있습니다. 이러한 문제를 해결하려면 분산 트랜잭션의 비즈니스 측면이 롤백 방지 및 멱등성을 갖춰야 합니다. - 세 가지 특징이 있습니다.
Exceptions
다음은 TCC 트랜잭션을 사용하여 이러한 예외를 설명합니다.
Empty 롤백:Cancel 메서드는 TCC 리소스 Try 메서드를 호출하지 않고 호출됩니다. 롤백을 비우고 바로 성공을 반환합니다.
이유는 지점 트랜잭션에 서비스 다운타임이 발생하거나 네트워크 이상이 발생하는 경우 지점 트랜잭션 호출이 실패로 기록되기 때문입니다. 이때 실제로 Try 단계가 실행되지 않고 장애가 복원되면 분산 트랜잭션이 실행됩니다. 취소되고 두 번째 단계가 호출되어 빈 롤백이 형성됩니다.
Idempotence:모든 요청에는 네트워크 이상 및 반복 요청이 있을 수 있으므로 모든 분산 트랜잭션 분기에서는 멱등성을 보장해야 합니다.
Suspension:Suspension은 배포를 위한 것입니다. 이러한 유형의 트랜잭션의 경우 2단계 취소 인터페이스는 Try 인터페이스보다 먼저 실행됩니다.
이유는 RPC가 Branch Transaction Try를 호출하면 먼저 Branch Transaction이 등록된 후 RPC 호출이 실행되기 때문입니다. 이때 RPC가 호출한 네트워크가 혼잡할 경우 RPC Time Out 후 TM이 RM에게 이를 알립니다. 발생할 수 있는 분산 트랜잭션 롤백 롤오버가 완료된 후 Try RPC 요청이 참가자에게 도달하여 실제로 실행됩니다.
위의 문제를 더 잘 이해하기 위해 네트워크 예외의 타이밍 다이어그램을 살펴보겠습니다.
위의 복잡한 네트워크 이상 상황에 대비하여 솔루션은 현재 여러 회사에서 권장하는 것은 비즈니스 측 고유 키를 사용하여 관련 작업이 완료되었는지 쿼리하면 성공이 직접 반환됩니다. 관련 판단 논리는 복잡하고 오류가 발생하기 쉬우며 비즈니스 부담이 큽니다.
하위 트랜잭션 장벽
프로젝트 https://github.com/yedf/dtm에서는 이 기술을 사용하여 이러한 효과를 얻을 수 있습니다.
모두. 이러한 요청은 하위 트랜잭션 장벽에 도달한 후 비정상적인 요청이 필터링되고 정상적인 요청은 장벽을 통과합니다. 개발자가 하위 트랜잭션 장벽을 사용한 후에는 위에서 언급한 모든 예외가 적절하게 처리되고 비즈니스 개발자는 실제 비즈니스 로직에만 집중하면 되며 부담이 크게 줄어듭니다.
하위 트랜잭션 배리어는 ThroughBarrierCall 메소드를 제공합니다. 메소드의 프로토타입은 다음과 같습니다.
func ThroughBarrierCall(db *sql.DB, transInfo *TransInfo, busiCall BusiFunc)
비즈니스 개발자는 BusiCall에서 자신만의 관련 로직을 작성하고 이 함수를 호출할 수 있습니다. ThroughBarrierCall은 빈 롤백 및 일시 중단과 같은 시나리오에서busiCall이 호출되지 않도록 보장합니다. 비즈니스가 반복적으로 호출될 때 한 번만 제출되도록 하는 멱등성 제어가 있습니다.
하위 트랜잭션 장벽은 TCC, SAGA, 트랜잭션 메시지 등을 관리하며 다른 영역으로도 확장 가능합니다.
하위 트랜잭션 장벽의 원리
하위 트랜잭션 장벽 기술의 원리는 지점 트랜잭션을 구축하는 것입니다. 고유 키를 사용하여 로컬 데이터베이스의 상태 테이블 sub_trans_barrier 전역 트랜잭션에 대한 트랜잭션 열기 id-sub-transaction id-sub-transaction 분기 이름 (try|confirm|cancel)
- Try 분기인 경우, 그런 다음 삽입 무시 insert gid-branchid-try를 삽입하고 삽입이 성공하면 장벽 내부 로직을 호출합니다
- Confirm 분기인 경우 삽입 무시 삽입 gid-branchid-confirm 삽입이 성공하면 장벽 내부 논리를 호출합니다. logic
- Cancel 브랜치인 경우,ignore insert gid-branchid-try를 삽입하고, gid-branchid -cancel을 삽입하고, try가 삽입되지 않고 취소가 성공적으로 삽입되면 장벽 내의 로직을 호출합니다
- 로직 장벽 내에서는 성공을 반환하고, 트랜잭션을 커밋하고, 성공을 반환합니다
- 장벽 내의 논리는 오류를 반환하고, 트랜잭션을 롤백하고, 오류를 반환합니다
이 메커니즘에서는 다음으로 네트워크 이상과 관련된 문제가 해결됩니다
- Empty 보상 제어--Try가 실행되지 않고 Cancel이 직접 실행되면 장벽 내의 논리를 사용하지 않고 취소가 gid-branchid-try에 성공적으로 삽입되어 빈 보상 제어를 보장합니다.
- 무능한 제어--고유 키를 사용할 수 없습니다.
- Anti-hanging 제어 - Try는 취소 후에 실행되며, 삽입된 gid-branchid-try가 실패하면 실행되지 않습니다. hang control
SAGA, 거래 메시지 등에 대해서도 유사한 메커니즘이 있습니다.
하위 트랜잭션 장벽 개요
서브 트랜잭션 장벽 기술은 https://github.com/yedf/dtm에서 최초로 구현된 알고리즘입니다. 간단하고 사용하기 쉬운 인터페이스 우선, 간단하고 구현하기 쉬운 알고리즘을 설계하고 간단하고 사용하기 쉬운 인터페이스를 제공하는 것이 중요합니다. 네트워크 예외 처리에서 해방됩니다.
이 기술은 현재 yedf/dtm 트랜잭션 관리자와 결합되어야 합니다. 현재 SDK는 Go 및 Python 언어 개발자에게 제공됩니다. 다른 언어용 SDK도 계획 중입니다. 기타 분산 거래 프레임워크의 경우 적절한 분산 거래 정보가 제공된다면 위의 원칙에 따라 기술을 신속하게 구현할 수 있습니다.
요약
이 기사에서는 분산 트랜잭션의 몇 가지 기본 이론을 소개하고 일반적으로 사용되는 분산 트랜잭션 솔루션을 설명합니다. 기사 후반부에서는 트랜잭션 예외에 대한 이유, 분류 및 우아한 솔루션도 제공됩니다.
yedf/dtm은 TCC, XA, SAGA, 트랜잭션 메시지, 최선의 알림(트랜잭션 메시지를 사용하여 구현됨)을 지원하고 HTTP 및 gRPC 프로토콜 지원을 제공하며 액세스가 매우 쉽습니다.
yedf/dtm은 Python, Java, PHP, C#, Node 및 기타 언어로 클라이언트를 지원했습니다. 각 언어에 대한 SDK를 참조하세요.
https://github.com/yedf/dtm 프로젝트를 방문하신 모든 분들을 환영하고 별표를 주시고 응원해주세요!