본문 바로가기

빅데이터/Kafka

카프카 source connector가 exactly-once를 지원하는 방법

KIP-618에서 Source connector의 exactly-once(일부) 지원을 건의하였고 이 내용은 3.3.0에서 처음 적용되었습니다.

 

https://cwiki.apache.org/confluence/display/KAFKA/KIP-618%3A+Exactly-Once+Support+for+Source+Connectors

 

KIP-618: Exactly-Once Support for Source Connectors - Apache Kafka - Apache Software Foundation

Status Current state: Accepted Discussion thread: here Voting thread: here JIRA: KAFKA-10000 - 이슈 세부사항 가져오는 중... 상태 ,  KAFKA-6080 - 이슈 세부사항 가져오는 중... 상태 Please keep the discussion on the mailing list r

cwiki.apache.org

 

1. 기존에는 source connector의 EOS를 지원하지 않았던 이유

기존에는 다음과 같은 방식으로 데이터를 처리하고 오프셋을 저장했습니다.

 

1. 소스 DB로 부터 데이터를 읽어서 토픽으로 send()

2. __connect-offsets에 읽은 오프셋까지 따로 커밋(저장)

 

위 방식은 별도의 처리로 이루어졌기 때문에 만약 워커가 죽어서 오프셋 저장이 되지 않으면 send()는 수행했지만 다시금 실행하는 즉, 두번의 처리(at-least-once)가 수행되었습니다. 그리고 추가적으로 좀비 태스크의 문제가 있었는데, 같은 소스 파티션에서 태스크가 어떠한 이유로 두번 이상 읽어서 중복이 발생하는 부분이 있어서 이를 다음과 같은 방식으로 해결하려고 했습니다.

 

1. 소스 레코드 전송 + 오프셋 저장을 '원자적'으로 수행

2. 좀비 태스크 팬싱(fencing)으로 중복 처리 하지 않음

 

2. 관련 메커니즘

같은 트랜잭션(원자적 처리)안에 소스 레코드 전송과 오프셋 커밋을 동시에 하는 것이 중요하다. 결과적으로 완벽하게 동시에 반영되어야지만 중복이나 누락없이 정확한 위치에서 읽기가 가능해지기 때문이다. 그렇기에 source connector로 전송되는 레코드는 'transaction record'로 전송되고 이에 따라 commit 또는 abort되어 처리된다. 즉, consumer 입장에서 topic을 읽기위해서는 isolation.level을 read_committed로 해야지만 정확히 한번처리된 데이터만 읽을 수 있게 된다. 

3. 설정하는 방법

exactly.once.source.support 옵션을 통해 이제 source connector는 exactly-once 전송을 수행할 수 있게 되었습니다. 관련 옵션의 설명은 다음과 같습니다.

- exactly.once.source.supprt : DISABLED(기본값), ENABLED, PREPARING

https://kafka.apache.org/39/documentation.html#connectconfigs_exactly.once.source.support

Whether to enable exactly once support for source connectors in the cluster by using transactions to write source records and their source offsets, and by proactively fencing out old task generations before bringing up new ones. To enable exactly-once source support on a new cluster, set this property to 'enabled'. To enable support on an existing cluster, first set to 'preparing' on every worker in the cluster, then set to 'enabled'. A rolling upgrade may be used for both changes. For more information on this feature, see the exactly-once source support documentation.
소스 커넥터에서 생성된 레코드와 해당 소스 오프셋을 트랜잭션으로 함께 기록하고, 새로운 태스크를 시작하기 전에 이전 세대의 태스크들을 적극적으로 펜싱하여 비활성화함으로써, 클러스터에서 소스 커넥터의 exactly-once 지원을 활성화할지 여부를 설정하는 옵션이다. 새로운 클러스터에서 처음부터 exactly-once 소스 지원을 사용하려면 이 값을 ‘enabled’로 설정하면 된다. 이미 운영 중인 클러스터에서는, 모든 워커에 대해 먼저 ‘preparing’으로 설정한 뒤, 그다음 단계에서 ‘enabled’로 설정해야 한다.

 

소스 커넥터 자체에서 exactly-once 처리를 지원하더라도 결과적으로 connect 클러스터 전체가 exactly-once 모드를 사용할 수 있도록 프레임워크 레벨에서 설정을 활성화 해야만 하고, 이 기능은 오직 distributed 모드(분산 커넥트)에서만 사용 가능하다. 

 

특이한 점은 '처음' 커넥트 클러스터를 실행한다면 해당 옵션을 'enabled'로 설정하면 되고, 만약에 롤링 업그레이드 등을 통해 기존에는 'disabled(default)'로 되어 있다면 'preparing'으로 설정한 뒤에 'enabled'로 다시 변경해야만 한다.