728x90
반응형
목적
cdc의 인프라 확장 시 스키마 레지스트리의 도입을 검토하기 위함
도입 배경
Kafka와 같은 메시지 시스템에서는 데이터 형식을 명시적으로 정의하지 않으면 생산자와 소비자 간의 데이터 해석이 일관되지 않을 수 있음
특히 메시지가 다양한 버전으로 진화하면서, 메타데이터와 데이터의 일관성을 유지하는 것이 복잡해짐
장단점
장점
- 메시지 크기 감소: 스키마를 분리해 중앙에서 관리함으로써 메시지 자체에 스키마를 포함할 필요가 없어지기 때문에 메시지 크기 감소
- 스키마 진화 지원: 스키마 레지스트리는 각 스키마의 버전을 관리하므로, 데이터 구조가 진화할 때도 호환성 문제가 발생하지 않도록 지원함 예를 들어, 새로운 필드를 추가하거나 제거할 때 이전 버전과의 호환성을 유지
- 생산자-소비자 간의 독립성: 스키마 레지스트리를 사용하면 생산자와 소비자가 서로 다른 스키마를 사용하더라도 호환성을 유지
- 데이터 품질 향상: 데이터의 스키마가 명확히 정의되므로, 잘못된 형식의 데이터가 Kafka에 들어가는 것을 방지
단점
- 추가 복잡성: 스키마 레지스트리 자체를 운영하고 관리해야 하는 관리 포인트가 발생
- 의존성 증가: 스키마 레지스트리와의 연동이 추가되면서 Kafka 메시지 시스템에 대한 의존성이 늘어날 수 있음. 예를 들어 만약 스키마 레지스트리가 다운되면 메시지 처리가 지연될 수 있음
- 성능 오버헤드: 스키마 레지스트리에 대한 요청/응답이 추가되면서 약간의 성능 저하가 발생할 수 있음 그러나 이 오버헤드는 매우 작은 편
지원하는 데이터 형식
- Avro(가장 적합)
- ProtoBuf
- JSON
그렇다면 파케이(parquet)는 왜 지원을 하지 않을까?
파케이는 컬럼 지향 데이터 형식으로 주로 olap에서 대량 데이터를 핸들링할 때 쓰인다.
즉, 한번에(하나의 트랜잭션에) 대량의 데이터를 다룰 때 파케이가 유리하고
cdc같은 단타성으로 여러번 날라가는 쿼리(oltp, 더 정확하게는 cdc 혹은 realtime 서비스)에서는 파케이가 부적합하다.
그러므로 컨슈밍 구간(플링크를 기준으로)에서는 Avro로 가져가되 타겟db에는 파케이로 저장하는 방식이 적합할 듯하다.
동작 방식
- 로컬 캐시에 없으면, 스키마 전송(등록)
Avro 프로듀서는 컨플루언트에서 제공하는 io.confluent.kafka.serializers.KafkaAvroSerializer 라는 새로운 직렬화를 사용해 스키마 레지스트리의 스키마가 유효한지 여부를 확인한다. 만약 스키마가 확인되지 않으면 Avro 프로듀서는 스키마를 등록하고 캐시한다. - 스키마 등록(ID 할당)
스키마 레지스트리는 현 스키마가 저장소에 저장된 스키마와 동일한 것인지, 진화한 스키마인지 확인한다. 스키마 레지스트리 자체적으로 각 스키마에 대해 고유 ID를 할당한다. 이 ID는 순차적으로 1씩 증가하지만, 반드시 연속적이진 않다. 스키마에 문제가 없다면 스키마 레지스트리라는 프로듀서에게 고유 ID를 응답한다. - 스키마 ID별 Avro 메시지 직렬화 전송
프로듀서는 스키마 레지스트리로부터 받은 스키마 ID를 참고해 메시지를 카프카로 전송한다. 이때 프로듀서는 스키마의 전체 내용이 아닌 오로지 메시지와 스키마 ID만 보낸다. JSON은 key:value 형태로 전체 메시지를 전송해야 하지만, Avro를 사용하면 프로듀서가 스키마 ID와 밸류만 메시지로 보내게 되어 카프카로 전송하는 전체 메시지의 크기를 줄일 수 있다. - 로컬 캐시에 없으면 스키마 ID별로 가져오기
Avro 컨슈머는 스키마 ID로 컨플루언트에서 제공하는 io.confluent.kafka.serializers.KafkaAvroDeserializer 라는 새로운 역직렬화를 사용해 카프카의 토픽에 저장된 메시지를 읽는다. 이때 컨슈머가 스키마 ID를 갖고있지 않다면 스키마 레지스트리로부터 가져온다.
참고
728x90
반응형