본문 바로가기

Archived(IT)/MSA

마이크로 서비스 패턴 #4 트랜잭션 관리

트랜잭션 관리?

(트랜잭션 :  데이터베이스의 상태를 변환시키는 하나의 논리적 기능을 수행하기 위한 작업의 단위 또는 한꺼번에 모두 수행되어야 할 일련의 연산들을 의미한다, ACID 트랜잭션이 대표적인 특성)

 

MSA에서는 #3 IPC와 같은 맥락으로 트랜잭션 관리가 조금 더 복합적이다.

하나의 DB 트랜잭션으로 처리하던 모놀리틱한 서비스가 아니기에 트랜잭션 관리가 복잡해지는 것이다.

자체 DB들을 지닌 여러 서비스들이 각각의 트랜잭션을 어떻게 관리할 수 있을까, 이런 부분들에 대해서 알아보고자 한다.


분산 트랜잭션? 사가(SAGA)

기존에는 분산 트랜잭션을 통해서 여러 서비스, DB들에 대해 데이터 일관성을 유지할 수 있었다.

그렇지만 동기 IPC에서 오는 낮은 가용성에 의해 최근까지 많은 신기술들과 접목하기에는 성능적 한계에 부딪힌다.

시스템은 일반적으로 일관성, 가용성, 분할 허용성 세 가지의 속성 중 두 가지만 지닐 수 있다고 한다.

(최근의 많은 아키텍쳐들은 성능을 위해 가용성을 선택한다)

 

트랜잭션 관리에 있어 중요한 부분인 일관성을 분산 트랜잭션 없이 수행 가능할까?

그에 대한 답이 바로 사가 패턴이다.

 

각 서비스를 트랜잭션 별로 실행하는데 메시지 또는 이벤트를 통해 다음 트랜잭션 단계를 트리거한다. 이러한 일련의 트랜잭션들을 흐름에 따라 진행하는데 단, 단계가 실패 하면 사가는 이전 트랜잭션을 막기 위한 역순으로 보상 트랜잭션을 실행한다.


사가 편성

사가는 단계를 편성하는 로직으로 구성된다.

트랜잭션 별로 호출하는 과정에 따라 모든 단계가 실행될 때까지 반복된다. 도중 하나라도 실패하면 보상 트랜잭션을 역순으로 실행하는데, 여기서 편성 로직은 크게 2가지가 존재한다.

 

 

1) 코레오그래피(Choreography): 의사 결정과 순서화를 사가 참여자에게 맡긴다. 사가 참여자는 이벤트 교환 방식으로 통신한다.

 

사가 참여자들끼리 이벤트를 수신하게 되면 트랜잭션을 처리한다. 이에 따라 일관성을 유지하면서도 낮은 결합도를 유지할 수 있게 되는 것이다. 단 2가지 통신 이슈를 고려해야 한다.

  • 사가 참여자가 자신의 DB를 업데이트 후 DB 트랜잭션의 일부로 이벤트를 발행해야 함
  • 사가 참여자는 자신이 수신한 이벤트와 자신이 가진 데이터를 연관지을 수 있어야 함

 

장점 > 단순함(서비스는 단순히 이벤트 발행 및 구독) , 느슨한 결합(이벤트를 구독할 뿐 참여자끼리 존재 모름)

단점 > 복잡도, 서비스 간 순환 의존성, 참여자 간 결합도 급증에 대한 경계(모든 서비스끼리 구독해야 함)

 

 

2) 오케스트레이션(orchestration): 사가 편성 로직을 사가 오케스트레이터에 중앙화한다. 사가 오케스트레이터는 사가 참여자에게 커맨드 메세지를 보내 수행할 작업을 지시한다.

 

모든 서비스들은 사가 오케스트레이터를 거쳐 진행한다. 

 

장점 > 의존 관계 단순화, 낮은 결합도(서비스는 오케스트레이터 호출 API만), 비즈니스 로직 단순화

단점 > 비즈니스 로직을 오케스트레이터에 과한 중앙화(깡통 서비스)

 

대부분 단순한 사가가 아니라면 오케스트레이션 형식 선호


비격리 문제 처리

 

ACID의 격리성은 동시에 실행 중인 여러 트랜잭션의 결과가 순서대로 진행한 결과와 동일함을 보장하는 속성이다.

(A 원자성, C 일관성, I 격리성 , D 지속성) 

 

그러나 사가는 ACD만 보장. 격리가 안되기에 anomaly(비정상) 현상이 나타날 수 있다.

(최근에는 많은 서비스들은 성능 향상을 위해 격리성을 낮추는 경향도 있다)

 

비정상은 크게 3가지 현상이 있다.

  • 소실된 업데이트(lost updates): 한 사가의 변경분을 다른 사가가 미처 못 읽고 덮어 쓴다.
  • 더티 읽기(dirty reads): 사가 업데이트를 하지 않은 변경분을 다른 트랜잭션이나 사가가 읽는다.
  • 퍼지/반복 불가능한 읽기(fuzzy/nonrepeatable reads): 한 사가의 상이한 두 단계가 같은 데이터를 읽어도 결과가 달라지는 현상. 다른 사가가 그 사이 업데이트를 했기 때문에 생기는 문제.

 

비정상 대책 방법

  • 시맨틱 락(semantic lock): 애플리케이션 수준의 락
  • 교환적 업데이트(commutative updates): 업데이트 작업은 어떤 순서로 실행해도 되게끔 설계
  • 비관적 관점(pessimistic view): 사가 단계 순서를 재조정하여 비즈니스 리스크를 최소화
  • 값 다시 읽기(reread value): 데이터를 덮어 쓸 때 그 전에 변경된 내용은 없는지 값을 다시 읽고 확인하여 더티 쓰기(dirty writes)를 방지
  • 버전 파일(version file): 순서를 재조정할 수 있게 업데이트를 기록
  • 값에 의한(by value): 요청별 비즈니스 위험성을 기준으로 동시성 메커니즘을 동적 선택

 

사가의 구조

  • 보상 가능 트랜잭션(compensatable transaction): 보상 트랜잭션으로 롤백 가능한 트랜잭션
  • 피벗 트랜잭션(pivot transaction): 사가의 진행/중단 지점. 피봇 트랜잭션이 커밋되면 사가는 완료될 때까지 실행. 피봇 트랜잭션은 보상 가능 트랜잭션, 재시도 가능한 트랜잭션 그 어느 쪽도 아니지만, 최종 보상 가능 트랜잭션 또는 최초 재시도 가능 트랜잭션이 될 수 있음
  • 재시도 가능 트랜잭션(retriable transaction): 피봇 트랜잭션 직후의 트랜잭션. 반드시 성공