Change Data Capture (CDC) 레이어를 PostgreSQL 트랜잭션 로그에 연결된 Debezium 커넥터를 사용하여 구현합니다. 이벤트를 Apache Kafka를 통해 스트리밍하고 메시지 내구성 및 보존을 보장하기 위해 로그 압축을 활성화합니다.
Apache Flink 또는 ksqlDB를 배포하여 상태ful 스트림 처리를 수행하고, S3 또는 GCS에 체크포인트를 통해 정확히 한 번 세마틱을 유지합니다. Avro 또는 Protobuf 형식의 Confluent Schema Registry를 사용하여 이전 및 이후 호환성 규칙을 강제하고, 진화하는 동안 소비자 중단을 방지합니다.
갈등 해결을 위해 메타데이터 레이어에서 벡터 클락 또는 버전 벡터를 구현하여 지역 간 인과 관계를 추적합니다. 비핵심 필드에 대해서는 마지막 쓰기 우선 (LWW)를 적용하고, 카운터 및 집합에 대해 CRDT 기반 병합 함수를 사용합니다. 최종 뷰를 ClickHouse 또는 Apache Druid에 물리화하여 분석을 수행하고, Narayana 또는 Saga 패턴과 같은 분산 트랜잭션 조정자를 통해 ACID 속성을 보장하여 뷰 저장소의 궁극적 일관성을 유지합니다.
GlobalMart, 국제 전자상거래 플랫폼, 블랙 프라이데이 이벤트 동안 중요한 데이터 부패 문제에 직면했습니다. 그들의 야간 배치 ETL 작업은 MySQL 트랜잭션 기록과 BigQuery 분석 대시보드 간의 4시간 지연을 발생시켜 재고 초과 판매 및 잘못된 가격 업데이트를 초래했습니다.
솔루션 A: 직접 CDC를 검색 인덱스로. 그들은 MySQL binlog를 Logstash를 사용하여 직접 Elasticsearch로 스트리밍하는 것을 고려했습니다. 이는 낮은 지연 시간과 간단한 설정을 제공했습니다. 그러나 테이블 간의 복잡한 조인 작업이 불가능해졌고, 스키마 변경 시 전체 Elasticsearch 재색인이 필요하여 6시간의 다운타임이 발생했습니다.
솔루션 B: 명령 쿼리 책임 분리(CQRS). 이 접근 방식은 Axon Framework를 사용하여 읽기 및 쓰기 모델을 분리했습니다. 뛰어난 감사 추적 및 유연성을 제공했지만, 전체 애플리케이션 리팩토링을 요구했습니다. 팀의 기존 모놀리식 Spring Boot 애플리케이션은 이벤트 소싱으로 쉽게 전환할 수 없었으며, 학습 곡선이 2개월 기한에 비해 너무 가파랐습니다.
솔루션 C: 스키마 레지스트리를 통한 스트리밍 물리화된 뷰. 그들은 Debezium을 사용하여 PostgreSQL에서 캡처하고, Kafka로 스트리밍하며, 비즈니스 로직을 적용해 Flink로 처리하고, ClickHouse로 전송했습니다. Confluent Schema Registry의 Avro 스키마는 CI/CD 중에 호환성 검사를 강제했습니다. 갈등 해결을 위해, 그들은 Kafka 헤더에 내장된 벡터 클락을 사용하여 지역 프로모션으로 인한 다양한 재고 수량에 대해 자동으로 병합할 수 있었습니다.
그들은 기존 SQL 스키마를 유지하면서 실시간 기능을 가능하게 하는 솔루션 C를 선택했습니다. Schema Registry는 칸리 출시 중에 호환되지 않는 스키마 변경을 거부하여 배포 실패를 방지했습니다.
그 결과로 120ms 종료 간 지연을 달성하고, 초당 50,000 트랜잭션을 지원하며, us-east-1 지역 중단 중 RPO를 0으로 유지하면서 보조 지역의 Kafka 미러 메이커 2 설정으로 전환했습니다.
물리화된 뷰에서 부분 업데이트를 방지하기 위해 CDC는 다중 테이블 트랜잭션 일관성을 어떻게 처리하나요?
많은 사람들은 Debezium이 테이블 간의 원자성을 자동으로 보장한다고 가정합니다. 실제로 CDC는 테이블마다 별도의 이벤트를 방출합니다. 일관성을 유지하려면 Transactional Outbox 패턴을 구현해야 합니다: 비즈니스 이벤트를 비즈니스 로직과 동일한 데이터베이스 트랜잭션 내의 아웃박스 테이블에 기록합니다. Debezium은 오직 아웃박스 테이블을 캡처하여 원자 이벤트 방출을 보장합니다. 또는, Debezium의 transaction.metadata 기능을 사용하여 소비자에서 트랜잭션 ID별로 이벤트를 그룹화하여 모든 관련 이벤트가 도착할 때까지 버퍼링한 후 뷰를 업데이트합니다.
지역 간 뷰에 대해 강력한 일관성보다 궁극적 일관성을 선택하는 경우는 언제이며, 특정 구현의 절충점은 무엇인가요?
후보자들은 종종 지연 비용을 고려하지 않고 강력한 일관성으로 기본 설정합니다. 강력한 일관성은 지역 간의 2단계 커밋 (2PC) 또는 Paxos/Raft 합의를 요구하며, 각 쓰기마다 100-300ms의 지연을 추가합니다. 이는 재무 장부나 재고 할당에 필요합니다. 추천 엔진이나 분석 대시보드의 경우, 벡터 클락을 사용하는 CRDT 또는 마지막 쓰기 우선을 사용하십시오. 절충점은 클라이언트 측 병합 로직의 복잡성 대 서버 측 조정입니다. CRDT는 불변 데이터 구조와 교환 가능한 연산을 요구하여 비즈니스 논리의 유연성을 제한하지만, 파트너(파트너에 따른 가용성 제공됨) 동안 가용성을 제공합니다 (CAP 정리에 따른 AP).
구식 필드 제거 시 스키마 진화가 다운스트림 소비자를 깨뜨리지 않도록 방지하는 방법은 무엇인가요?
대부분은 최근 호환성을 이해하지만(새 코드가 오래된 데이터 읽음) 이전 호환성을 놓칩니다(오래된 코드가 새로운 데이터 읽음). 필드를 제거할 때는 즉시 삭제하지 마세요. 대신, Avro의 기본값을 사용하여 Schema Registry에 배포하고, 소비자를 새 스키마로 배포한 후, 두 번의 릴리즈 주기 후에 생산자에서 필드 쓰기를 중지합니다. 브레이킹 변경(예: 타입 변경)의 경우, 별도 주제를 통한 스키마 진화를 구현합니다: events-v2 주제로 작성하면서 events-v1을 유지하고 브리지를 소비하여 다운타임 없이 점진적으로 마이그레이션할 수 있게 합니다.