CDC(변경 데이터 캡처) 소개
변경 데이터 캡처(CDC)는 데이터베이스 작업(삽입, 업데이트, 삭제)에서 행 수준에서 변경 사항을 추적하고 이벤트 순서대로 다른 시스템에 알리는 데 사용되는 기술입니다. 재해 복구 시나리오에서 CDC는 주로 기본 데이터베이스와 백업 데이터베이스 간의 데이터를 동기화하여 기본 데이터베이스에서 보조 데이터베이스로 실시간 데이터 동기화를 가능하게 합니다.
source ----------> CDC ----------> sink
아파치 씨터널 CDC
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은 다음을 통해 이를 처리합니다.
- 먼저, 분할을 읽기 전에 binlog 위치(로우 워터마크)를 확인합니다.
-
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에서는 마커가 모든 독자, 분할 열거자, 작성자 및 기타 노드에 전송되고 각각의 노드는 메모리 상태를 유지합니다.