본문 바로가기
MSA

[MSA][Saga] SAGA 패턴

by Real Iron 2023. 12. 22.

패턴: 사가

이 패턴에 대해 더 자세히 알고 싶으십니까?

Saga, API Composition 및 CQRS 패턴을 사용하여 여러 서비스에 걸쳐 작업을 설계하는 방법을 알려주는 자습형 온라인 부트캠프를 살펴보세요 .

정가는 1인당 $395이지만 HVQSSCEY 쿠폰을 사용하여 $120에 가입하세요. (2024년 1월 11일까지 유효)

문맥

서비스당 데이터베이스 패턴을 적용했습니다 . 각 서비스에는 자체 데이터베이스가 있습니다. 그러나 일부 비즈니스 트랜잭션은 여러 서비스에 걸쳐 있으므로 서비스에 걸쳐 있는 트랜잭션을 구현하는 메커니즘이 필요합니다. 예를 들어, 고객에게 신용 한도가 있는 전자상거래 상점을 구축한다고 가정해 보겠습니다. 애플리케이션에서는 새 주문이 고객의 신용 한도를 초과하지 않도록 해야 합니다. 주문과 고객은 서로 다른 서비스가 소유한 서로 다른 데이터베이스에 있으므로 애플리케이션은 단순히 로컬 ACID 트랜잭션을 사용할 수 없습니다.

문제

서비스 전반에 걸쳐 트랜잭션을 구현하는 방법은 무엇입니까?

  • 2PC는 옵션이 아닙니다

해결책

여러 서비스에 걸쳐 있는 각 비즈니스 트랜잭션을 하나의 이야기로 구현하세요. 무용담은 일련의 지역 거래입니다. 각 로컬 트랜잭션은 데이터베이스를 업데이트하고 메시지나 이벤트를 게시하여 사가의 다음 로컬 트랜잭션을 트리거합니다. 비즈니스 규칙을 위반하여 로컬 트랜잭션이 실패하는 경우 Saga는 이전 로컬 트랜잭션에 의해 수행된 변경 사항을 취소하는 일련의 보상 트랜잭션을 실행합니다.

조정 사가에는 두 가지 방법이 있습니다.

  • 안무 - 각 로컬 트랜잭션은 다른 서비스에서 로컬 트랜잭션을 트리거하는 도메인 이벤트를 게시합니다.
  • 오케스트레이션 - 오케스트레이터(객체)는 참가자에게 실행할 로컬 트랜잭션을 알려줍니다.

예: 안무 기반 사가

이 접근 방식을 사용하는 전자 상거래 애플리케이션은 다음 단계로 구성된 안무 기반 사가를 사용하여 주문을 생성합니다.

  1. Order Service요청을 받고 상태  생성 POST /orders합니다.OrderPENDING
  2. 그런 다음 Order Created이벤트를 발생시킵니다.
  3.  Customer Service이벤트 핸들러가 크레딧을 예약하려고 시도합니다.
  4. 그런 다음 결과를 나타내는 이벤트를 내보냅니다.
  5.  OrderService이벤트 핸들러는 다음을 승인하거나 거부합니다.Order

예: 오케스트레이션 기반 사가

이 접근 방식을 사용하는 전자 상거래 애플리케이션은 다음 단계로 구성된 오케스트레이션 기반 사가를 사용하여 주문을 생성합니다.

  1. Order Service요청을 수신 하고 POST /ordersSaga Create Order오케스트레이터를 생성합니다.
  2. 사가 오케스트레이터는 상태 Order에서PENDING
  3. 그런 다음 Reserve Credit명령을 보냅니다.Customer Service
  4. Customer Service신용을 확보하려는 시도
  5. 그런 다음 결과를 나타내는 응답 메시지를 다시 보냅니다.
  6. 사가 오케스트레이터는 이를 승인하거나 거부합니다.Order

결과 컨텍스트

이 패턴에는 다음과 같은 이점이 있습니다.

  • 분산 트랜잭션을 사용하지 않고도 애플리케이션이 여러 서비스에서 데이터 일관성을 유지할 수 있습니다.

이 솔루션에는 다음과 같은 단점이 있습니다.

  • 프로그래밍 모델은 더 복잡합니다. 예를 들어, 개발자는 이전 시리즈의 변경 사항을 명시적으로 취소하는 보상 트랜잭션을 설계해야 합니다.

또한 해결해야 할 다음과 같은 문제도 있습니다.

  • 신뢰성을 유지하려면 서비스가 데이터베이스를 원자적으로 업데이트 하고 메시지/이벤트를 게시해야 합니다. 데이터베이스와 메시지 브로커를 포괄하는 분산 트랜잭션의 전통적인 메커니즘을 사용할 수 없습니다. 대신 아래 나열된 패턴 중 하나를 사용해야 합니다.
  • 동기 요청(예: HTTP)을 사용하여 비동기 흐름이 발생하는 사가를 시작하는 클라이언트는 POST /orders해당 결과를 결정할 수 있어야 합니다. 여러 가지 옵션이 있으며 각각 서로 다른 장단점이 있습니다.
    • 서비스는 사가가 완료되면, 예를 들어 OrderApproved또는 OrderRejected이벤트를 수신하면 응답을 다시 보냅니다.
    • 서비스는 orderID사가를 시작한 후 응답(예: 포함)을 다시 보내고 클라이언트는 GET /orders/{orderID}결과를 결정하기 위해 주기적으로 폴링(예: ) 합니다.
    • orderID서비스는 사가를 시작한 후 응답(예: 포함)을 다시 보낸 다음, 사가가 완료되면 클라이언트에 이벤트(예: 웹소켓, 웹 후크 등)를 보냅니다.

더 알아보기

예제 코드

다음 예에서는 고객 및 주문 예를 다양한 방식으로 구현합니다.