검증 프레임워크는 이벤트 소싱의 변경 불가능한 추가 전용 특성과 최소 1회 배달 및 레거시 시스템 대기 시간의 기계적 제약을 조정하는 데 중점을 둡니다. 인프라 배달 의미론에 의존하기보다는 애플리케이션 계층에서 아이도메포턴시 보장을 설정하여 중복 Kafka 메시지가 부작용 없이 동일한 이벤트 저장 항목을 생성하도록 해야 합니다. 아키텍처는 CQRS 읽기 모델을 속도를 위해 최적화하고 비동기 변경 데이터 캡처(CDC)를 사용하여 레거시 Oracle 감사 저장소를 차단 없이 보수하는 방식으로 고속 거래 경로와 규정 준수 보고를 분리합니다.
모놀리식 Java EE 플랫폼에서 Spring Boot 마이크로서비스로 이전 중인 정량적 거래 회사는 바로 이러한 딜레마에 직면했습니다. 이 도메인은 SEC 규칙 17a-4(b) 감사 추적 요구 사항을 충족하기 위해 가격 업데이트, 취소, 실행 등 모든 주문 수정을 변경 불가능한 이벤트로 추적해야 했습니다. 그러나 그들의 Kafka 클러스터는 가용성을 우선시하여 최소 1회 배달로 구성되어 있었고, 이로 인해 소비자 재시도 로직이 중복 거래 이벤트를 생성하여 포지션 계산을 손상시켰습니다. 동시에, 리스크 관리 대시보드는 읽기 모델을 쿼리하여 실시간 노출 계산을 하던 중, 네트워크 혼잡으로 인해 규정 준수 Oracle 12c 데이터베이스에 대한 동기식 쓰기를 시도하면서 300ms의 대기 시간 급증을 경험했습니다. 이로 인해 변동성이 큰 시장 상황에서 50ms 리스크 임계값을 위반했습니다.
솔루션 1: Kafka에서 정확히 1회 의미론 활성화
팀은 Kafka를 정확히 1회 처리(EOS)로 재구성하여 트랜잭션 ID와 아이도메포턴트 생산자를 사용하는 방안을 고려했습니다. 이 접근 방식은 각 메시지가 소비자 오프셋과 원자적으로 커밋되도록 보장하여 프로토콜 수준에서 중복을 제거했을 것입니다. 장점으로는 애플리케이션 코드 변경 없이 중복을 본래적으로 처리하고 파티션 내에서 엄격한 정렬 보장을 유지할 수 있다는 점이 포함됐습니다. 그러나 단점은 장애가 크며: 트랜잭션 조정 오버헤드로 인해 메시지당 18-25ms의 대기 시간이 추가되었고, ZooKeeper 의존성으로 인해 거래 파이프라인이 조정자 선출 동안 중단될 수 있는 단일 실패 지점이 발생했습니다. 게다가, 이는 기본 Oracle ODBC 병목 현상을 해결하지 못하고, 단순히 중복 처리 복잡성을 상류로 이동시켰습니다.
솔루션 2: Cassandra를 중간 핫 저장소로 배포
대안으로는 Kafka와 Oracle 사이에 Cassandra 클러스터를 삽입하여 고속 버퍼 역할을 하도록 제안했습니다. Apache Spark Streaming이 Cassandra 스트림을 윈도우 기반으로 중복 제거한 후 Oracle에 묶어 쓰도록 합니다. 장점으로는 Cassandra가 밀리초 단위의 대기 시간으로 높은 쓰기 처리량을 처리할 수 있으며, 실시간 처리를 규정 준수 스토리지와 분리할 수 있다는 점이 있습니다. 그러나 단점으로는 두 개의 이질적인 저장 시스템을 유지하는 것이 네트워크 분할 중 분할 뇌 시나리오를 생성하여 상당한 운영 위험을 초래했습니다. 또한, SEC 감사자는 중간의 가변 저장소가 변경 불가능한 감사 추적의 진실의 원천으로 작용할 수 있는 능력에 대해 회의적인 입장을 보였습니다. 다수의 다른 장르의 지속성 계층에서 ACID 속성을 보장하는 복잡성은 프로젝트 타임라인을 위협했습니다.
솔루션 3: Redis 읽기 모델 및 Debezium CDC와 함께 클라이언트 측 아이도메포턴시 구현
선택된 해결책은 이벤트 핸들러 내에서 합성 자연 키(집계 ID + 시퀀스 번호)를 사용하여 클라이언트 측 아이도메포턴시를 구현하여 중복 Kafka 메시지가 인식되고 상태 변이 없이 폐기되도록 보장했습니다. 대기 시간 요구를 만족시키기 위해 팀은 각 마이크로서비스와 함께 위치하여 이벤트 프로젝션을 사용하여 읽기 모델을 구현하는 Redis 클러스터를 배포하여 리스크 계산을 위한 쿼리 응답 시간을 10ms 미만으로 달성했습니다. 성능에 영향 없이 Oracle 규정 준수 요구 사항을 충족하기 위해 그들은 Debezium을 구현하여 이벤트 스토어의 PostgreSQL 백업 데이터베이스에서 변경 사항을 캡처하고 비동기적으로 Oracle로 스트리밍하여, 감사 보고를 위해 궁극적인 일관성을 수용하면서도 거래 작업에 강력한 일관성을 유지하도록 했습니다.
이 접근 방식은 인프라 제약이 아닌 애플리케이션 논리를 통해 중복 이벤트 리스크를 해결하고, 메모리 캐싱을 통해 공격적인 대기 시간 SLA를 충족시키며 감사 무결성을 희생하지 않으며, 레거시 Oracle 투자를 존중하여 실시간의 중요한 경로와 분리했기 때문에 성공적이었습니다. 그 결과 시스템이 초당 150,000 이벤트를 처리하며 평균 12ms 읽기 대기 시간, 6개월 운영 동안 감지된 중복 거래 없음, 데이터 변경 불가능성이나 추적 가능성에 대한 발견 없이 전체 SEC 규정 준수 확인을 통과했습니다.
네트워크 분할이 발생할 때 분산 집계 전반에서 이벤트 순서를 어떻게 유지합니까?
지원자는 종종 전역 정렬이 필요하거나 달성할 수 있다고 가정하여 아키텍처 병목 현상을 초래합니다. 분산 이벤트 소싱에서 정렬은 시스템 전반이 아니라 집계 루트 수준에서만 제한적으로 정의해야 합니다. 각 집계 스트림 내에서 인과 관계를 설정하기 위해 벡터 클럭이나 논리적 단조 시퀀스 번호를 구현해야 합니다. Kafka 파티션은 집계 경계와 일대일로 정렬되어 플랫폼의 파티션 내 정렬 보장을 활용해야 합니다. 네트워크 분할이 발생하면 시스템은 서로 다른 집계 간의 일시적인 불일치(최종 일관성)를 받아들이면서도 각 집계 내에서 낙관적 동시성 제어 및 버전 검사를 통해 엄격한 일관성을 보장하여 손실된 업데이트를 방지하면서 분산 잠금을 요구하지 않아야 합니다.
이벤트 소싱과 감사 추적을 위한 단순한 변경 데이터 캡처(CDC)의 건축적 구별은 무엇입니까?
많은 지원자들이 이러한 패턴을 혼동하여 CDC만으로 감사 요구 사항이 충족된다고 제안합니다. CDC는 데이터베이스 레이어에서 상태 변경을 캡처합니다(예: "행 42가 A에서 B로 업데이트됨"), 반면 이벤트 소싱은 상태 변경이 발생하기 전 비즈니스 이벤트로서 도메인 의도를 캡처합니다(예: "고객이 프리미엄 등급으로 업그레이드됨" 및 контекст에 대한 메타데이터). SEC 규정 준수를 위해 이벤트 소싱은 비즈니스 논리 및 결정 맥락을 보존하므로 감사 능력이 우수합니다. 거래 결정을 재구성할 때 도메인 이벤트는 주문이 수정된 이유를 드러내지만, CDC 로그는 단지 수정이 발생했음을 보여줍니다. 이벤트 저장소는 기록 시스템으로 작용하지만, CDC는 동기화 메커니즘입니다.
변경 불가능한 이벤트 저장소 내에서 GDPR 제17조(지우기 권리) 요청을 어떻게 처리합니까?
이는 변경 불가능성과 프라이버시 규정 간의 근본적인 갈등을 나타냅니다. 지원자들은 종종 이벤트를 물리적으로 삭제하거나 수정하는 것을 틀리게 제안하지만, 이는 감사 추적 무결성을 위반합니다. 올바른 접근 방식은 암호화 지우기를 사용하여 이벤트 페이로드 내에서 개인 식별 정보(PII)를 암호화하고 별도의 키 관리 서비스(KMS)에 저장된 데이터 암호화 키를 활용하는 것입니다. 지우기 요청이 발생하면 이벤트 데이터 대신 암호화 키를 삭제하여 PII가 영구적으로 읽을 수 없도록 하여 감사 요구 사항을 준수하면서 이벤트 구조와 집계 상태 전환을 보존합니다. 대안으로, 이후 스트림에서 민감한 필드를 tombstone 값으로 덮어쓰는 보상 이벤트를 구현하여 변경 불가능한 기록을 유지하면서 현재 프로젝션이 회복 가능한 개인 데이터를 포함하지 않도록 할 수 있습니다.