변경 데이터 캡처(CDC)는 데이터베이스 작업(삽입, 업데이트, 삭제)에서 행 수준에서 변경 사항을 추적하고 이벤트 순서대로 다른 시스템에 알리는 데 사용되는 기술입니다. 재해 복구 시나리오에서 CDC는 주로 기본 데이터베이스와 백업 데이터베이스 간의 데이터를 동기화하여 기본 데이터베이스에서 보조 데이터베이스로 실시간 데이터 동기화를 가능하게 합니다.
source ----------> CDC ----------> sink
SeaTunnel CDC는 두 가지 유형의 데이터 동기화를 제공합니다.
잠금 없는 스냅샷 동기화 단계는 Debezium과 같은 많은 기존 CDC 플랫폼이 과거 데이터 동기화 중에 테이블을 잠글 수 있기 때문에 강조됩니다. 스냅샷 읽기는 데이터베이스의 과거 데이터를 동기화하는 프로세스입니다. 이 프로세스의 기본 흐름은 다음과 같습니다.
storage -------------> splitEnumerator ---------- split ----------> reader ^ | | | \----------------- report -----------/
분할 파티셔닝
splitEnumerator
(분할 분배기)는 지정된 필드(예: 테이블 ID 또는 고유 키)와 정의된 단계 크기를 기준으로 테이블 데이터를 여러 개의 분할로 분할합니다.
병렬 처리
각 분할은 병렬 판독을 위해 다른 판독기에 할당됩니다. 단일 판독기는 하나의 연결을 차지합니다.
이벤트 피드백
분할에 대한 읽기 작업을 완료한 후 각 리더는 splitEnumerator
에 진행 상황을 보고합니다. 분할에 대한 메타데이터는 다음과 같이 제공됩니다.
String splitId # Routing ID TableId tableId # Table ID SeatunnelRowType splitKeyType # The type of field used for partitioning Object splitStart # Start point of the partition Object splitEnd # End point of the partition
리더가 분할 정보를 받으면 적절한 SQL 문을 생성합니다. 시작하기 전에 데이터베이스 로그에 현재 분할의 해당 위치를 기록합니다. 현재 분할을 완료한 후 리더는 다음 데이터와 함께 splitEnumerator
에 진행 상황을 보고합니다.
String splitId # Split ID Offset highWatermark # Log position corresponding to the split, for future validation
증분 동기화 단계는 스냅샷 읽기 단계 이후에 시작됩니다. 이 단계에서는 소스 데이터베이스에서 발생하는 모든 변경 사항이 캡처되어 실시간으로 백업 데이터베이스에 동기화됩니다. 이 단계는 데이터베이스 로그(예: MySQL binlog)를 수신합니다. 증분 추적은 일반적으로 binlog의 중복 풀을 피하고 데이터베이스 부하를 줄이기 위해 단일 스레드로 이루어집니다. 따라서 하나의 리더만 사용되어 단일 연결을 차지합니다.
data log -------------> splitEnumerator ---------- split ----------> reader ^ | | | \----------------- report -----------/
증분 동기화 단계에서는 스냅샷 단계의 모든 분할과 테이블이 단일 분할로 결합됩니다. 이 단계 동안의 분할 메타데이터는 다음과 같습니다.
String splitId Offset startingOffset # The lowest log start position among all splits Offset endingOffset # Log end position, or "continuous" if ongoing, eg, in the incremental phase List<TableId> tableIds Map<TableId, Offset> tableWatermarks # Watermark for all splits List<CompletedSnapshotSplitInfo> completedSnapshotSplitInfos # Snapshot phase split details
CompletedSnapshotSplitInfo
필드는 다음과 같습니다.
String splitId TableId tableId SeatunnelRowType splitKeyType Object splitStart Object splitEnd Offset watermark # Corresponds to the highWatermark in the report
증분 단계의 분할에는 스냅샷 단계의 모든 분할에 대한 워터마크가 포함됩니다. 최소 워터마크는 증분 동기화의 시작점으로 선택됩니다.
스냅샷 읽기 또는 증분 읽기 단계에서 데이터베이스도 동기화를 위해 변경될 수 있습니다. 정확히 하나의 전달을 어떻게 보장합니까?
예를 들어 스냅샷 읽기 단계에서는 행 k3
삽입, k2
업데이트, k1
삭제와 같은 변경이 발생하는 동안 분할이 동기화됩니다. 읽기 프로세스 중에 작업 식별을 사용하지 않으면 업데이트가 손실될 수 있습니다. SeaTunnel은 다음을 통해 이를 처리합니다.
split{start, end}
범위에서 데이터를 읽습니다.
high = low
이면 분할에 대한 데이터가 읽기 중에 변경되지 않았습니다. (high - low) > 0
이면 처리 중에 변경이 발생했습니다. 그런 경우 SeaTunnel은 다음을 수행합니다.
low watermark
에서 high watermark
까지 순서대로 변경 사항을 적용하여 메모리 내 테이블에서 작업을 재생합니다.
insert k3 update k2 delete k1 | | | vvv bin log --|---------------------------------------------------|-- log offset low watermark high watermark CDC reads: k1 k3 k4 | Replays v Real data: k2 k3' k4
증분 단계를 시작하기 전에 SeaTunnel은 먼저 이전 단계의 모든 분할을 검증합니다. 분할 간에 데이터가 업데이트될 수 있습니다. 예를 들어, 분할1과 분할2 사이에 새 레코드가 삽입되면 스냅샷 단계에서 누락될 수 있습니다. 분할 간에 이 데이터를 복구하기 위해 SeaTunnel은 다음 접근 방식을 따릅니다.
completedSnapshotSplitInfos
확인하여 데이터가 분할에서 처리되었는지 확인합니다. 그렇지 않은 경우 분할 간의 데이터로 간주되므로 수정해야 합니다.
|------------filter split2-----------------| |----filter split1------| data log -|-----------------------|------------------|----------------------------------|- log offset min watermark split1 watermark split2 watermark max watermark
CDC를 일시 중지하고 재개하는 건 어때요? SeaTunnel은 분산 스냅샷 알고리즘(Chandy-Lamport)을 사용합니다.
시스템에 두 개의 프로세스 p1
과 p2
가 있다고 가정합니다. 여기서 p1
세 개의 변수 X1 Y1 Z1
가지고 있고 p2
세 개의 변수 X2 Y2 Z2
가지고 있습니다. 초기 상태는 다음과 같습니다.
p1 p2 X1:0 X2:4 Y1:0 Y2:2 Z1:0 Z2:3
이 시점에서 p1
글로벌 스냅샷을 시작합니다. p1
먼저 프로세스 상태를 기록한 다음 마커를 p2
로 보냅니다.
마커가 p2
에 도달하기 전에 p2
메시지 M
p1
로 보냅니다.
p1 p2 X1:0 -------marker-------> X2:4 Y1:0 <---------M---------- Y2:2 Z1:0 Z2:3
마커를 수신하면 p2
상태를 기록하고 p1
메시지 M
수신합니다. p1
이미 로컬 스냅샷을 수행했으므로 메시지 M
만 로깅하면 됩니다. 최종 스냅샷은 다음과 같습니다.
p1 M p2 X1:0 X2:4 Y1:0 Y2:2 Z1:0 Z2:3
SeaTunnel CDC에서는 마커가 모든 독자, 분할 열거자, 작성자 및 기타 노드에 전송되고 각각의 노드는 메모리 상태를 유지합니다.