>  기사  >  Java  >  Java Spring Boot 분산 트랜잭션 문제를 해결하는 방법

Java Spring Boot 분산 트랜잭션 문제를 해결하는 방법

PHPz
PHPz앞으로
2023-04-18 12:34:021477검색

1. 역보상이란

먼저, 분산거래 관련 정보를 보면 역보상이라는 용어를 자주 접하게 됩니다. 역보상이란 무엇인가요?

예를 들어보겠습니다. 이제 A, B, C라는 세 개의 마이크로서비스가 있다고 가정해 보겠습니다. 이제 B와 C가 동시에 성공하거나 실패하도록 하기 위해 A 서비스에서 B와 C 서비스를 각각 호출합니다. , 유통 공식 업무를 사용해야합니다. 그러나 로컬 트랜잭션에 대한 이전 이해에 따르면 B와 C의 로컬 트랜잭션의 경우 서비스 B의 트랜잭션이 완료되고 제출된 후 이제 서비스 C의 트랜잭션에 예외가 발생하여 B가 이미 롤백되어야 합니다. 제출했습니다. 어떻게 롤백하나요?

지금 이야기하는 롤백은 사실 MySQL redo 로그를 통한 롤백이라는 전통적인 의미가 아니고, 업데이트 SQL을 사용해 B 서비스에서 변경된 데이터를 복원하는 것입니다.

이것을 역보상이라고 합니다!

2. 기본 개념 검토

Seata에는 세 가지 핵심 개념이 있습니다.

  • TC(트랜잭션 코디네이터) - 트랜잭션 코디네이터: 글로벌 및 지점 트랜잭션의 상태를 유지하고 글로벌 트랜잭션 제출 또는 롤백을 구동합니다.

  • TM(트랜잭션 관리자) - 트랜잭션 관리자: 글로벌 트랜잭션의 범위를 정의하고, 글로벌 트랜잭션을 시작하고, 글로벌 트랜잭션을 커밋 또는 롤백합니다.

  • RM(Resource Manager) - Resource Manager: 브랜치 트랜잭션 처리를 위한 리소스(Resource)를 관리하고, TC와 대화하여 브랜치 트랜잭션을 등록하고 브랜치 트랜잭션 상태를 보고하며, 브랜치 트랜잭션을 커밋 또는 롤백하도록 유도합니다.

그 중 TC는 별도로 배포되는 서버이고, TM과 RM은 애플리케이션에 내장된 클라이언트입니다.

다음 사진을 살펴보겠습니다.

Java Spring Boot 분산 트랜잭션 문제를 해결하는 방법

이 사진은 기본적으로 이 세 가지 개념을 명확하게 설명합니다.

사실 이 사진을 보지 않고도 우리는 아마도 분산 트랜잭션의 구현 원리를 짐작할 수 있을 것입니다. 먼저 글로벌 트랜잭션 코디네이터(TC)가 있어야 하며, 각 로컬 트랜잭션(RM)이 실행을 시작하거나, 실행될 때 그 과정에서 글로벌 트랜잭션 코디네이터는 각 브랜치 트랜잭션의 현재 실행 상태를 알고 있으며, 모든 로컬 트랜잭션이 성공적으로 실행되었음을 확인하면 모든 사람에게 제출합니다. 누군가가 이 트랜잭션을 실행하지 못했다는 사실을 발견하면 모든 사람에게 함께 롤백하도록 알립니다(물론 이 롤백은 실제 롤백이 아니라 역보상입니다). 그렇다면 거래는 언제 시작되고 끝나나요? 즉, 거래의 경계는 어디에 있습니까? 시타의 분산 트랜잭션은 모두 @GlobalTransactional 주석을 통해 구현됩니다. 즉, 이 주석을 어디에 추가해야 할까요? 이 주석을 추가하는 장소는 실제로 트랜잭션 관리자 TM입니다.

위의 소개 후에 친구들은 Seata를 사용하여 분산 거래를 구현하는 것이 생각만큼 어렵지 않으며 원리도 매우 쉽다는 것을 이해해야 합니다.

Seata에는 4가지 모드가 있습니다. 다음에 소개되는 4가지 모드는 실제로 로컬 트랜잭션이 실패할 때 롤백하는 방법에 대해 이야기하고 있습니다. 이는 나중에 설명할 네 가지 분산 트랜잭션 모드입니다.

3. 2단계 제출이란

먼저 아래 그림을 보세요:

Java Spring Boot 분산 트랜잭션 문제를 해결하는 방법

이 그림에는 세 가지 개념이 포함됩니다. 응용 프로그램 자체입니다.

  • RM: RM은 트랜잭션에 참여하는 리소스 관리자입니다. 대부분의 경우 분산 트랜잭션에는 여러 RM이 포함됩니다.

  • TM: TM은 분산 트랜잭션을 생성하고 분산 트랜잭션에서 각 하위 트랜잭션의 실행 및 상태를 조정하는 트랜잭션 관리자입니다. 하위 트랜잭션은 RM에서 수행되는 특정 작업을 나타냅니다.

  • 그럼 Two-Phase Commit(약칭 2PC) 제출이란 무엇인가요?

    2단계 제출의 진실은 매우 간단합니다. 송 형제가 2단계 제출을 설명하기 위해 간단한 예를 제공합니다.

  • 예를 들어 다음 그림은 다음과 같습니다.

저희는 보관 및 주문을 요청합니다. 각각 Business Account에서 이 세 가지 작업은 동시에 성공하거나 실패해야 하지만 이 세 가지 서비스는 서로 다른 서비스에 있으므로 이 세 가지 서비스의 작업을 별도로 실행하도록 할 수만 있습니다. 두 단계 중 첫 번째 단계입니다. 1단계 실행이 완료된 후, 세 가지 서비스 중 일부가 실행에 실패했을 수 있으므로 서두르지 마세요. 이때 세 서비스는 첫 번째 단계의 실행 결과를 트랜잭션 코디네이터에게 보고해야 합니다. 트랜잭션 코디네이터는 메시지를 받은 후 세 가지 서비스 중 첫 번째 단계가 성공적으로 실행되면 세 가지 서비스 중 하나라도 실행에 실패하면 세 가지 트랜잭션에 롤백하라는 알림이 전달됩니다. 각기.

이를 2단계 커밋이라고 합니다.

요약하자면, 2단계 제출에서는 거래가 참가자(예: 위 그림의 각 특정 서비스)와 코디네이터로 나누어지며, 참가자는 코디네이터에게 작업의 성공 여부를 통보한 다음, 코디네이터는 모든 참가자의 피드백 정보를 기반으로 결정을 내립니다. 참가자가 작업을 제출하거나 작업을 중단하려는 경우 여기에서 참가자는 RM으로 이해될 수 있으며 코디네이터는 TM으로 이해될 수 있습니다.

그러나 Seata의 다양한 분산 거래 모드는 기본적으로 2단계 제출을 기반으로 진화하므로 완전히 동일하지는 않습니다.

4. AT 모드

AT 모드는 전자동 거래 롤백 모드입니다.

전반적으로 AT 모드는 2단계 커밋 프로토콜의 진화입니다.

  • 1단계: 비즈니스 데이터와 롤백 로그 레코드가 동일한 로컬 트랜잭션에서 커밋되어 로컬 잠금 및 연결 리소스가 해제됩니다.

  • 두 번째 단계는 두 가지 상황으로 나뉩니다. 2.1 비동기식 제출은 매우 빠르게 완료됩니다. 2.2 Rollback은 1단계 롤백 로그를 통해 역보상을 수행합니다.

일반적인 논리는 위와 같습니다. 특정 사례를 통해 AT 모드가 어떻게 작동하는지 살펴보겠습니다.

다음과 같은 비즈니스 테이블 제품이 있다고 가정합니다.

Java Spring Boot 분산 트랜잭션 문제를 해결하는 방법

이제 우리는 다음 업데이트 작업:

update product set name = 'GTS' where name = 'TXC';

단계는 다음과 같습니다.

1단계:

  • Parse SQL: SQL 유형(UPDATE), 테이블(제품), 조건(여기서 이름 = ')을 가져옵니다. TXC') 및 기타 관련 정보.

  • 사전 쿼리 이미지: 파싱을 통해 얻은 조건 정보를 기반으로 쿼리문을 생성하고 데이터를 찾습니다(업데이트 전 데이터 찾기).

  • 위의 업데이트 SQL을 실행합니다.

  • 사후 미러 쿼리: 사전 미러 결과에 따라 기본 키를 통해 데이터를 찾습니다.

  • 롤백 로그 삽입: 미러 전후 데이터와 비즈니스 SQL 관련 정보를 롤백 로그 기록으로 결합하여 UNDO_LOG 테이블에 삽입합니다.

  • 제출하기 전에 TC에 지점을 등록하세요. 제품 테이블에서 기본 키 값이 1인 레코드에 대한 전역 잠금을 신청하세요.

  • 로컬 트랜잭션 제출: 이전 단계에서 생성된 UNDO LOG와 함께 비즈니스 데이터 업데이트가 제출됩니다.

  • 현지 거래 제출 결과를 TC에 보고하세요.

두 번째 단계:

두 번째 단계는 커밋 또는 롤백의 두 가지 상황으로 나뉩니다.

먼저 롤백 단계를 살펴보겠습니다.

  • 먼저 TC로부터 브랜치 롤백 요청을 받고 로컬 트랜잭션을 시작한 후 다음 작업을 수행합니다.

  • XID와 Branch ID를 통해 해당 UNDO LOG 레코드를 찾습니다. (이 레코드는 데이터 수정 전후의 해당 이미지를 저장합니다.)

  • 데이터 검증: UNDO LOG에 게시된 이미지를 현재 데이터와 비교하여 차이가 있다면 현재 글로벌 트랜잭션이 아닌 다른 작업에 의해 데이터가 수정되었음을 의미합니다. 이 상황은 구성 정책에 따라 처리되어야 합니다.

  • UNDO LOG의 이전 이미지 및 비즈니스 SQL 관련 정보를 기반으로 롤백 문 생성 및 실행: update product set name = 'TXC' where id = 1;update product set name = 'TXC' where id = 1;

  • 提交本地事务。并把本地事务的执行结果(即分支事务回滚的结果)上报给 TC。

再来看提交步骤:

  • 收到 TC 的分支提交请求,把请求放入一个异步任务的队列中,马上返回提交成功的结果给 TC。

  • 异步任务阶段的分支提交请求将异步和批量地删除相应 UNDO LOG 记录。

大致上就是这样一个步骤,思路还是比较清晰的,就是当你要更新一条记录的时候,系统将这条记录更新之前和更新之后的内容生成一段 JSON 并存入 undo log 表中,将来要回滚的话,就根据 undo log 中的记录去更新数据(反向补偿),将来要是不回滚的话,就删除 undo log 中的记录。

在整个过程中,开发者只需要额外创建一张 undo log 表就行了,然后给需要处理全局事务的地方加上 @GlobalTransactional

제출 지역 문제. 그리고 로컬 트랜잭션의 실행 결과(즉, 지점 트랜잭션 롤백 결과)를 TC에 보고한다.

제출 단계를 다시 살펴보겠습니다.

Java Spring Boot 분산 트랜잭션 문제를 해결하는 방법은 TC의 브랜치 제출 요청을 수신하고 해당 요청을 비동기 작업 대기열에 넣은 다음 성공적인 제출 결과를 즉시 TC에 반환합니다.

🎜비동기 작업 단계의 분기 제출 요청은 해당 UNDO LOG 레코드를 비동기식으로 일괄 삭제합니다. 🎜🎜🎜🎜기본적으로 그런 단계입니다. 레코드를 업데이트하려는 경우 시스템은 레코드 업데이트 전후의 내용에 대해 JSON을 생성하여 실행 취소 로그 테이블에 저장합니다. 나중에 롤백하고 싶다면 언두 로그의 기록을 바탕으로 데이터를 업데이트하세요(역보상). 나중에 롤백하고 싶지 않다면 언두 로그의 기록을 삭제하세요. 🎜🎜전체 프로세스에서 개발자는 추가 실행 취소 로그 테이블을 생성한 다음 전역 트랜잭션을 처리해야 하는 곳에 @GlobalTransactional 주석을 추가하기만 하면 됩니다. 🎜🎜기타 제출, 롤백 및 롤백은 모두 완전 자동이므로 더 쉽게 수행할 수 있습니다. 따라서 프로젝트에서 분산 트랜잭션을 처리하기 위해 Seata를 사용하기로 선택한 경우 AT 모드를 사용할 확률은 여전히 ​​상당히 높습니다. 🎜🎜5. TCC 모드🎜🎜TCC(Try-Confirm-Cancel) 모드도 약간 수동적인 느낌이 들지만 AT와는 다른 과정을 살펴보겠습니다. 🎜🎜🎜공식 웹사이트에 TCC의 흐름도가 있으니 살펴보겠습니다. 🎜🎜🎜🎜🎜🎜보시다시피 TCC도 두 단계로 나뉩니다. 🎜
  • 첫 번째 단계는 준비입니다. 이 단계에서는 주로 은행 이체 등의 리소스 감지 및 예약을 수행합니다. 이 단계에서는 먼저 사용자의 자금이 충분한지 확인합니다. 예외를 직접 던집니다. 충분하다면 먼저 동결됩니다.

  • 두 번째 단계는 커밋 또는 롤백입니다. 이는 주로 각 분기 트랜잭션의 첫 번째 단계가 완료될 때까지 기다리는 것입니다. 각 실행은 TC 통계 후에 자체 상황을 보고합니다. 각 지점 트랜잭션에 이상이 없는 것으로 확인된 후 TC가 지점 트랜잭션에 이상이 있다고 판단하면 모두에게 함께 제출하도록 알리고 모든 사람에게 롤백하도록 알립니다.

그렇다면 친구들은 위 프로세스에 준비, 커밋, 롤백이라는 총 세 가지 방법이 포함되어 있다는 것을 발견했을 것입니다. 이 세 가지 방법은 완전히 사용자 정의 방법이므로 직접 구현해야 합니다. TCC가 수동 모드인 시작.

AT와 비교하면 TCC 모드는 실제로 기본 데이터베이스의 트랜잭션 지원에 의존하지 않는다는 것을 모두가 발견했습니다. 즉, 기본 데이터베이스가 트랜잭션을 지원하지 않아도 상관이 없습니다. 준비, 커밋, 롤백은 개발자가 직접 작성했고, 이 세 가지 방법에 해당하는 프로세스를 원활하게 진행하면 됩니다.

6. XA 모드

MySQL 데이터베이스의 XA 트랜잭션을 이해했다면 Seata의 XA 모드가 무엇인지 이해하게 될 것입니다.

XA 사양은 X/Open 조직에서 정의한 분산 트랜잭션 처리(DTP, Distributed Transaction Process) 표준입니다.

XA 사양은 전역 트랜잭션 관리자와 로컬 리소스 관리자 간의 인터페이스를 설명합니다. XA 사양의 목적은 동일한 트랜잭션에서 여러 리소스(예: 데이터베이스, 애플리케이션 서버, 메시지 큐 등)에 액세스할 수 있도록 하여 ACID 속성이 애플리케이션 전체에서 유효하게 유지되도록 하는 것입니다.

XA 사양은 2단계 커밋을 사용하여 모든 리소스가 특정 트랜잭션을 동시에 커밋하거나 롤백하도록 보장합니다.

XA 사양은 1990년대 초에 제안되었습니다. 현재 거의 모든 주류 데이터베이스는 XA 사양을 지원합니다.

XA 트랜잭션은 2단계 커밋 프로토콜을 기반으로 합니다. 모든 거래 참여자가 준비 작업(1단계)을 완료했는지 확인하려면 거래 코디네이터가 필요합니다. 코디네이터는 모든 참가자가 준비가 되었다는 메시지를 받으면 모든 트랜잭션을 커밋할 수 있음을 알립니다(2단계). MySQL은 코디네이터(트랜잭션 관리자)가 아닌 이 XA 트랜잭션의 참여자 역할을 합니다.

MySQL의 XA 트랜잭션은 내부 XA와 외부 XA로 구분됩니다. 외부 XA는 외부 분산 트랜잭션에 참여할 수 있으며, 애플리케이션 계층이 코디네이터로 개입해야 합니다. 내부 XA 트랜잭션은 Binlog를 코디네이터로 사용하여 동일한 인스턴스에서 엔진 간 트랜잭션에 사용됩니다. 커밋이 필요합니다. 정보는 분산 내부 XA 트랜잭션인 바이너리 로그에 기록됩니다. 단, 바이너리 로그의 참가자는 MySQL 자체입니다. MySQL은 XA 트랜잭션에서 코디네이터가 아닌 참여자 역할을 합니다.

즉, MySQL은 XA 사양을 통해 자연스럽게 분산 트랜잭션을 구현할 수 있지만 일부 외부 애플리케이션의 지원만 필요합니다. Seata에서 XA 모드 사용 과정을 살펴보겠습니다.

먼저 공식 사진을 보세요:

Java Spring Boot 분산 트랜잭션 문제를 해결하는 방법

보시다시피 이것도 2단계 제출입니다.

  • 1단계: 비즈니스 SQL 작업은 XA 분기인 XA에서 수행됩니다. 분기가 완료된 후 XA 준비가 실행되고 RM의 XA 프로토콜 지원을 통해 지속성이 보장됩니다(즉, 후속 사고로 인해 롤백 실패가 발생하지 않음).

  • 두 번째 단계는 커밋 또는 롤백 두 가지 상황으로 나뉩니다.

  • 분기 커밋: XA 분기의 커밋을 실행합니다.

  • 분기 롤백: XA 분기의 롤백을 실행합니다. 차이점은 XA에서의 롤백입니다. 모드는 역보상이 아니라 전통적인 의미로 이해하는 롤백입니다.

  • 7. 사가 모드

마지막으로 사가 모드를 살펴보겠습니다. 이 모드는 거의 사용되지 않으므로 그냥 이해하시면 됩니다.

saga 모드는 Seata에서 제공하는 긴 트랜잭션 솔루션입니다. 그러나 긴 트랜잭션은 비효율적이고 쉽게 교착 상태를 일으킬 수 있으므로 개발 시 피해야 합니다.

이 사가 모드는 개발자가 먼저 프로세스 엔진을 그려서 전체 트랜잭션에 관련된 모든 메서드를 포함합니다. 각 메서드가 반환하는 것은 정상이고, 반환되는 것은 비정상입니다. 비정상이라면 계속해서 내려갑니다. 비정상이면 또 다른 프로세스 세트가 실행됩니다. 즉, 첫 번째 세트는 다양한 정상 상황에 대한 실행 프로세스입니다. 두 번째 세트는 예외 발생 후 실행 프로세스입니다.

녹색은 일반적인 프로세스이고, 빨간색은 예외 발생 후 롤백되는 프로세스입니다. 롤백(Rollback)도 일종의 역보상이다.

위 내용은 Java Spring Boot 분산 트랜잭션 문제를 해결하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 yisu.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제