Postgres 트랜잭션, 분산 시스템의 숨겨진 초능력

Postgres transactions are a distributed systems superpower

Postgres 트랜잭션, 분산 시스템의 숨겨진 초능력

워크플로우 상태와 데이터를 분리하면 복잡성이 증가합니다. 저는 DBOS 를 통해 워크플로우 상태를 Postgres 데이터와 함께 배치하는 방식을 제안합니다. 이를 통해 분산 시스템의 신뢰성을 높이고, ACID 트랜잭션의 강력한 힘을 자연스럽게 활용할 수 있습니다.

워크플로우 상태를 데이터와 함께 배치하면, 분산 시스템의 복잡성이 사라지고 Postgres 트랜잭션이 진정한 초능력이 됩니다.
  1. mrkeen

    몇 년 전 면접에서 이 문제로 인해 면접을 포기한 적이 있습니다.

    기술 질문 중 하나가 "데이터베이스와 메시지 큐가 있을 때, 업데이트를 양쪽 모두에 적용하거나 양쪽 모두에 적용하지 않는 방법 (즉, 트랜잭션적으로) 은 무엇인가"였습니다.

    잠깐 고민한 후 "저도 할 수 없고, 당신도 할 수 없습니다"라고 답변했습니다. 그리고 당시에는 그렇게 불리던 복제 상태 머신 (replicated-state-machine), Write-Ahead-Log, 이벤트 소싱 (event-sourcing) 등의 일반적인 접근법을 제안하며, 유일한 실용적인 해결책은 최종 일관성 (eventual consistency) 에 의존하는 것이라고 말했습니다.

    면접관이 Outbox 패턴에 대해 들어본 적이 있는지 물었으니, 설명을 들었습니다. 역시 이 글에서 설명하는 내용과 유사했습니다. 데이터베이스 D 와 메시지 큐 Q 를横跨하는 트랜잭션의 비결은 다음과 같습니다:

    (D,Q)

    D 를 두 부분 (State 와 Outbox) 으로 나누어 그 두 부분 사이에서 트랜잭션을 수행하고

    (S,O) Q

    그다음 D 와 Q 사이에서 트랜잭션이 수행된 것처럼 행동하는 것입니다.

  2. jdw64

    제 이해로는 워크플로우 진행 단위와 데이터베이스 커밋 단위를 1 대 1 로 정렬한다는 뜻인 것 같습니다. 즉, 워크플로우의 각 단계가 데이터베이스 커밋 단위가 되는 것입니다. 그래서 Outbox 패턴이 단순해지는 것입니다. 하지만 그 대가로 데이터베이스 자체가 워크플로우와 강하게 결합하게 되어, 나중에 아키텍처적으로 분리하기 어려워집니다. 물론 공정하게 말하자면, 저는 거의 데이터베이스를 분리할 필요가 없었습니다.

    대부분의 서비스에서 메시지 브로커나 워크플로우 엔진은 자주 교체하지만, 데이터베이스는 거의 항상 그대로 유지됩니다.

    제가 이 내용을 올바르게 이해했는지 잘 모르겠습니다.

  3. munk-a

    우리는 클라이언트 이메일 발송을 위한 외부 서비스 상호작용에 대해 트랜잭션의 원자성을 활용하고 안전장치 (fail-safe) 접근 방식을 적용했습니다. 이는 물론 공식적인 큐를 사용하여도 가능하지만, 매우 유사하게 작동하며 오늘날 우리가 가지고 있는 것과 동일한 보장을 제공할 것입니다 (그리고 당시에는 인프라 비용을 정당화하기엔 규모가 너무 작았습니다). 내부적으로는 대기 상태 (pending state) 의 데이터를 계산된 상태 (computed state) 로 변환하는 복잡한 로직을 수행하는 작업들이 있으며, 이는 데이터가 성공적으로 전환되도록 보장하기 위해 DB 의 원자성에 의존합니다. 이러한 작업들은 모두 매우 견고하지만, 2 차 영속성 저장소 (secondary persistence store) 가 관여될 경우 트랜잭션 보장은 어떤 형태로든 타협해야 합니다. 이메일 발송 예시에서 우리는 알림이 정확히 한 번만 전송된다는 보장을 받는 것보다 클라이언트가 모든 알림을 받는다는 보장을 받는 것이 더 중요하다는 견해를 가지고 있습니다. 따라서 우리의 발송 메커니즘은 이메일 발송이 성공했음을 확인한 후, 해당 메시지를 대기 목록에서 제거하는 트랜잭션을 닫는 것입니다.

    태양 플레어 등 어떤 이유로든 잠재적인 손실이 발생할 수 있는 시간 창은 항상 존재할 것입니다. 하지만 이러한 시스템을 설계할 때의 핵심은 시스템이 어떻게 실패할 수 있는지 인지하고, 그 결과를 수용한 다음, 각 영속성 커밋 사이사이의 사이클/로직 거리를 가능한 한 줄이도록 노력하는 것입니다. 로직은 돌이킬 수 없는 행동이 발생하기 전에 가능한 한 많은 사전 작업을 수행하도록 앞쪽으로 배치되어야 하며, 그런 다음 돌이킬 수 없는 행동은 …

  4. cloudie78

    축하합니다. 여러분은 뮤텍스 (mutex) 를 발견했습니다.

    정말 분산 시스템인가요, 아니면 중앙 데이터베이스를 가진 서비스들의 집합일 뿐인가요?

  5. Crowberry

    우리는 메인 애플리케이션 데이터베이스에 상주하는 자체 Pubsub 솔루션을 보유하고 있는데, 글에서 설명한 내용과 거의 정확히 일치합니다. 그리고 이를 통해 허용되는 원자성은 정말로 훌륭합니다!

이 날의 다른 글

2026-07-07