아키텍처는 하이브리드 논리 시계를 사용하여 작업을 주문하는 결정론적 거래 시퀀서를 중심으로 하며, 물리적 시간 대신 사용되어 TrueTime 기반 시스템에 내재된 시계 편차 의존성을 제거한다. 조정자는 Calvin 프로토콜의 변형을 구현하여 거래 의도를 실행 전에 다수의 샤드 리더에게 복제하여 결정을 보장하고, 분산 잠금을 사용하지 않고 결정론적 스케줄링을 통해 직렬 가능성을 보장한다. TLA+ 사양은 조정자의 상태 전이를 모델링하며, 시스템이 부분적인 네트워크 분할 동안에도 안전성(엄격한 직렬 가능성)과 생존성(모든 커밋된 거래가 결국 완료됨)을 유지하는지를 형식적으로 검증한다.
조정자는 WAL(Write-Ahead Log)에 거래 로그를 지속하며, 내구성을 위해 Paxos 합의를 이용한다. 샤드 프로시는 기본 저장 엔진—PostgreSQL, MongoDB 또는 Cassandra—을 추상화하여 실행 엔진을 위한 통합 인터페이스를 제공한다. 충돌 감지는 시퀀싱 단계에서 구성된 의존성 그래프를 사용하여 비충돌 거래의 동시 실행을 허용하며 직렬 순서와의 동등성을 유지한다.
글로벌 투자 은행은 무형의 Oracle 데이터베이스에서 AWS 및 Azure 지역에 걸쳐 샤드 아키텍처로 그들의 거래 결제 시스템을 마이그레이션해야 했다. 주요 도전 과제는 서로 다른 데이터베이스 기술에 저장된 여러 자산 클래스에 걸쳐 거래의 원자적 정산을 보장하는 것이었다—주식은 PostgreSQL에서, 파생상품은 ScyllaDB에서 관리했다—동기화를 위해 원자 시계나 GPS 시간 소스를 배포하지 않고.
제안된 솔루션 중 하나는 Narayana 거래 관리자가 관리하는 2단계 커밋(2PC) 프로토콜을 사용하는 표준 XA 거래를 활용했다. 이 접근 방식은 강력한 일관성과 성숙한 생태계 지원을 제공했지만, 준비 단계에서 조정자가 실패할 경우 샤드가 잠금을 계속 보유하게 되어 생존성 요건을 위반하는 차단 동작을 초래했다.
또 다른 대안은 Axon Framework를 통해 구현된 Saga 패턴을 고려했으며, 롤백 시나리오에 대한 보상 거래를 사용했다. 이는 높은 가용성을 제공하고 분산 잠금을 피하게 했지만 엄격한 직렬 가능성을 희생했다—중간 상태가 관찰될 수 없어야 하는 금융 정산에서는 용납될 수 없는 결과였다. 그리고 비가역적인 외부 시장 운영에 대한 보상 로직은 지나치게 복잡했다.
선택된 아키텍처는 TLA+ 형식 검증을 갖춘 Calvin 영감을 받은 결정론적 조정자를 구현했다. 시스템은 거래 결제 거래를 Raft로 조정 로그를 사용하는 복제 상태 기계로 시퀀싱한 후, 모든 샤드에서 동일한 순서로 idempotent 저장 프로시저를 사용하여 실행했다. 이는 실행 중 분산 잠금의 필요성을 제거하고 TLA+ 모델 점검을 통해 시스템이 교차 네트워크 분할 중에 교착 상태에 빠지거나 정산을 잃지 않을 수 있다는 것을 수학적으로 증명 가능하게 했다.
배포 결과는 레거시 Oracle 시스템에 비해 거래 결제 대기 시간을 40% 감소시켰으며, 클라우드 간의 ACID 보장을 완벽하게 유지했다. 이후 지역 전체의 AWS 정전 동안에도 시스템은 수동 개입 없이 거래를 계속 처리하여 형식적으로 입증된 생존 가능성을 검증했다.
엄격한 직렬 가능성과 선형 가능성의 근본적인 차이점은 무엇인가? 그리고 왜 분산 거래 조정자가 일반적으로 전자를 목표로 하는가?
엄격한 직렬 가능성은 직렬 가능성(거래는 어떤 순서로 실행되는 것처럼 보인다)과 선형 가능성의 실시간 제약(거래는 다음 거래가 시작되기 전에 완료된다)을 결합한다. 선형 가능성은 단일 객체 작업에 적용되는 반면, 엄격한 직렬 가능성은 다중 객체 거래로 이를 확장한다. 후보자들은 종종 이를 혼동하여 단일 키 선형 가능성을 보장하나 여러 키 간의 쓰기 편차와 같은 이상을 방지하지 못하는 시스템을 설계한다. 조정자는 일반적으로 거래의 글로벌 순서를 설정하여 엄격한 직렬 가능성을 달성하며—대개 시퀀싱 레이어나 타임스탬프 오라클을 통해—반면 선형 가능성만으로는 교차 샤드 순서 보장 없이 샤드 별로 만족할 수 있다.
왜 2단계 커밋(2PC) 프로토콜이 조정자 실패 시 무한정 차단되는가, 그리고 네트워크 분할 하에서 3단계 커밋(3PC)이 이를 해결하지 못하는 이유는 무엇인가?
2PC에서, 준비 단계에서 참가자가 "예"라고 투표하면, 글로벌 커밋/중단 결정이 조정자로부터 수신될 때까지 잠금을 유지한다. 조정자가 모든 투표를 받은 후 결정을 방송하기 전 실패하면, 참가자는 불확실한 상태가 되어 잠금이 걸려 있어 가용성을 위반하게 된다. 3PC는 사전 커밋 단계와 타임아웃 기반 진행을 추가하여 이를 해결하려 하지만, 네트워크 분할 하에서 참가자는 실패한 조정자와 분리된 조정자를 구분할 수 없다. 이는 서로 다른 파티션에서 상충되는 결정을 내리는 분리된 뇌 상태를 초래하여 일관성을 위반하게 된다. 근본적인 문제는 FLP 불가능성이 비동기적 시스템 내에서 단지 하나의 고장 프로세스라도 있을 경우 결정론적 합의가 불가능하다고 증명하기 때문에, 어떤 커밋 프로토콜은 특정 실패 모드에서 차단(안전) 또는 잠재적 불일치(생존 가능성 중)에 대해 선택해야 한다는 것이다.
TLA+는 거래 조정자에서 생존 가능성 속성을 어떻게 검증하며, "결국 커밋된다" 대 "데이터를 결코 잃지 않는다"를 표현하는 특정 시간 논리 연산자는 무엇인가?
**TLA+**는 시간을 다루는 논리를 사용하여 좋은 일이 결국 발생한다(생존 가능성)와 나쁜 일이 결코 발생하지 않는다(안전)를 지정한다. 모든 시작된 거래가 결국 완료된다는 생존성 속성은 결국 연산자(◇)를 사용하여 표현되며, 일반적으로 Initiated(t) ~> Committed(t) (유도)로 적혀, 거래 t가 시작되면 결국 커밋되거나 중단된다는 의미이다. "데이터를 결코 잃지 않는다"와 같은 안전 속성은 항상 연산자(□)를 사용하여 표현되며, □(Committed(t) ⇒ ◇(Query(t) = Value))로 쓰여, 커밋된 후에는 값이 항상 결국 읽힐 수 있다는 의미이다. 후보자들은 종종 생존 가능성 검사를 위해 공정성 가정이 필요하다는 것을 놓친다—약한 공정성(WF_vars(Action))은 동작이 계속 가능할 경우 반드시 결국 발생해야 함을 보장하여 조정자가 단순히 단계를 멈추는 무한한 대기 상태를 예방한다. 이러한 공정성 제약 없이, TLA+ 모델은 아무것도 하지 않음으로써 생존 가능성 속성을 간단히 만족할 수 있다.