3 minute read

대부분의 클라우드 서비스는 분산 트랜잭션이 야기하는 운영상의 문제 때문에 분산 트랜잭션을 구현하지 않는다.

분산 트랜잭션의 일부 구현은 심각한 성능 저하를 수반하는기도 한다. 예를 들어, MySQL의 분산 트랜잭션은 단일 노드 트랜잭션보다 10배 이상 느린 것으로 보고되었다.

2단계 커밋의 오버헤드는 대부분 크래시 복구에 필요한 추가 디스크 강제 동기화(fsync)와 추가 네트워크 라운드 트립으로 인한 것이다.

그러나 분산 트랜잭션을 완전히 무시하기보다는 좀 더 자세히 살펴봐야 한다. 왜냐하면, 분산 트랜잭션에서 배울 수 있는 중요한 교훈이 있기 때문입니다. 먼저 “분산화된 트랜잭션”이 무엇을 의미하는지에 대해 정확히 알아야 한다.

분산 트랜잭션에는 서로 다른 두 가지 유형이 혼용되는 경우가 많다.

데이터베이스 내부 분산 트랜잭션

일부 분산 데이터베이스(즉, 표준 구성에서 복제 및 파티셔닝을 사용하는 데이터베이스)는 해당 데이터베이스의 노드 간에 내부 트랜잭션을 지원한다. 예를 들어, VoltDB와 MySQL Cluster의 NDB 스토리지 엔진은 내부 트랜잭션을 지원하며, 트랜잭션에 참여하는 모든 노드는 동일한 데이터베이스 소프트웨어를 실행한다.

이기종 분산 트랜잭션

이기종 트랜잭션에서 참여자는 서로 다른 공급업체의 두 데이터베이스 또는 메시지 브로커와 같은 두 개 이상의 서로 다른 기술이다. 이러한 시스템 간의 분산 트랜잭션은 내부적으로 완전히 다른 시스템일지라도 원자 커밋을 보장해야 한다.

데이터베이스 내부 트랜잭션은 다른 시스템과 호환될 필요가 없으므로 어떤 프로토콜이든 사용할 수 있고 특정 기술에 특화된 최적화를 적용할 수 있디. 이러한 이유로 데이터베이스 내부 분산 트랜잭션은 종종 매우 잘 작동하지만, 이기종 기술에 걸친 트랜잭션은 훨씬 더 까다롭다.

정확한 한 번의 메시지 처리

이기종 분산 트랜잭션을 사용하면 다양한 시스템을 강력한 방식으로 통합할 수 있다. 예를 들어, 메시지 큐의 메시지는 메시지 처리를 위한 데이터베이스 트랜잭션이 성공적으로 커밋된 경우에만 처리된 것으로 승인될 수 있다. 이는 메시지 승인과 데이터베이스 쓰기를 단일 트랜잭션으로 원자 단위로 커밋함으로써 구현된다. 분산 트랜잭션을 지원하면 메시지 브로커와 데이터베이스가 서로 다른 컴퓨터에서 실행되는 서로 관련이 없는 두 기술인 경우에도 가능하다.

메시지 전달이나 데이터베이스 트랜잭션 중 하나라도 실패하면 둘 다 중단되므로 메시지 브로커는 나중에 메시지를 안전하게 다시 전달할 수 있다. 따라서 메시지와 메시지 처리의 부작용을 원자 단위로 커밋함으로써 메시지가 성공하기까지 몇 번의 재시도가 필요하더라도 메시지가 정확히 한 번만 효과적으로 처리되도록 할 수 있다.

그러나 이러한 분산 트랜잭션은 트랜잭션의 영향을 받는 모든 시스템이 동일한 원자 커밋 프로토콜을 사용할 수 있는 경우에만 가능하다. 예를 들어 메시지 처리의 부작용이 이메일을 보내는 것이라고 하자. 이메일 서버가 2단계 커밋을 지원하지 않는다면, 메시지 처리가 실패하여 재시도할 경우 이메일이 두 번 이상 전송될 수 있다. 그러나 트랜잭션 중단 시 메시지 처리의 모든 부작용이 롤백되면 아무 일도 없었던 것처럼 처리 단계를 안전하게 다시 시도할 수 있다.

XA 트랜잭션

X/Open XA(eXtended Architecture의 약자)는 이기종 기술에서 2단계 커밋을 구현하기 위한 1991년에 도입된 표준이다.

XA는 많은 기존 관계형 데이터베이스(PostgreSQL, MySQL, DB2, SQL Server, Oracle 포함)와 메시징 브로커(ActiveMQ, HornetQ, MSMQ, IBM MQ 포함)에서 지원된다. XA는 네트워크 프로토콜이 아니라 트랜잭션 코디네이터와의 인터페이스를 위한 C API일 뿐입니다. 이 API에 대한 바인딩은 다른 언어에도 존재한다. 예를 들어, Java EE 애플리케이션의 세계에서 XA 트랜잭션은 Java 트랜잭션 API(JTA)를 사용하여 구현되며, 이는 JDBC(Java 데이터베이스 연결)를 사용하는 데이터베이스용 드라이버와 JMS(Java 메시지 서비스) API를 사용하는 메시지 브로커용 드라이버에 의해 지원된다.

분산 트랜잭션의 한계

XA 트랜잭션은 여러 참여자 데이터 시스템을 서로 일관되게 유지할 수 있다. , 하지만 운영상의 문제도 야기한다. 특히 트랜잭션 코디네이터는 그 자체로 일종의 데이터베이스(트랜잭션 결과가 저장되는 곳)이므로 다른 중요한 데이터베이스와 마찬가지로 주의 깊게 접근해야 한다는 점이 핵심이다:

코디네이터가 단일 장애 지점이 된다

코디네이터가 복제되지 않고 단일 컴퓨터에서만 실행되는 경우, 코디네이터의 장애로 인해 다른 애플리케이션 서버가 의심스러운 트랜잭션이 보유한 잠금을 차단할 수 있으므로 전체 시스템의 장애 지점이 될 수 있다. 대부분의 코디네이터 구현은 기본적으로 가용성이 높지 않거나 초보적인 복제 지원만 제공한다.

애플리케이션의 일부가 된다

많은 서버 측 애플리케이션은 모든 영구 상태가 데이터베이스에 저장되는 상태 비저장 모델(HTTP에서 선호)로 개발되며, 이는 애플리케이션 서버를 마음대로 추가 및 제거할 수 있다는 장점이 있다. 그러나 코디네이터가 애플리케이션 서버의 일부가 되면 배포의 성격이 달라진다. 갑자기 코디네이터의 로그가 시스템 상태의 중요한 부분이 되며, 충돌 후 의심스러운 트랜잭션을 복구하려면 코디네이터 로그가 필요하기 때문에 데이터베이스 자체만큼이나 중요해진다. 이러한 애플리케이션 서버는 더 이상 스테이트리스 상태가 아니다.

최저 공통 분모

XA는 다양한 데이터 시스템과 호환되어야 하므로, 최저 공통 분모가 반드시 필요하다. 예를 들어, 서로 다른 시스템에서 교착 상태를 감지할 수 없다. 서로 다른 시스템에서 충돌을 식별하는 프로토콜이 필요하기 때문에 SSI(직렬화 가능한 격리)와는 작동하지 않는다.