Skip to content

Commit

Permalink
Create 8장 “정확히 한 번” 의미 구조.md
Browse files Browse the repository at this point in the history
  • Loading branch information
Emilia0608 authored Aug 21, 2024
1 parent c3cdcd9 commit 8b42613
Showing 1 changed file with 122 additions and 0 deletions.
122 changes: 122 additions & 0 deletions 5주차/이지윤/8장 “정확히 한 번” 의미 구조.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# 8장 “정확히 한 번” 의미 구조

태그: 카프카 핵심 가이드
주차: 4

- 7장 → “최소 한 번” 전달에 초점
- = 메세지 중복의 가능성 잔재
- → “정확히 한 번”
- 두 개의 핵심 기능
- 멱등적 프로듀서 idempotent producer: 프로듀서 재시도로 인해 발생하는 중복 방지
- 트랜잭션 의미 구조: 스트림 처리 애플리케이션에서 “정확히 한 번“ 처리 보장

## 1. 멱등적 프로듀서

- 멱등적 idempotent: 동일한 작업을 여러 번 실행해도 한 번 실행한 것과 결과가 같은 서비스

### 멱등적 프로듀서의 작동 원리

- 멱등적 프로듀서 기능 사용 시, 모든 메세지는 고유한 프로듀서 ID와 시퀀스 넘버를 가지게 됨
- 대상 토픽 및 파티션과 이 두 값 합치면 → 각 메세지의 고유한 식별자
- 작동 실패 시 멱등적 프로듀서 처리 방식
- 프로듀서 재시작
- 프로듀서는 초기화 과정에서 카프카 브로커로부터 프로듀서 ID 생성 받음
- 새 프로듀서가 기존 프로듀서가 이미 전송한 메세지를 다시 전송할 경우, 메세지 중복 발생 알 수 없음
- 브로커 장애
- 컨트롤러는 장애가 난 브로커가 리더를 맡고 있었던 파티션들에 대해 새 리더 선출
- 리더가 새 메세지 쓰여질 때마다 인-메모리 프로듀서 상태에 저장된 최근 5개의 시퀀스 넘버 업데이트
- 예전 리더가 복귀하는 경우
- 재시작 후에는 인-메모리 프로듀서 상태 메모리 저장 X
- 크래시 복구 작업 진행되는 동안, 프로듀서 상태는 더 오래된 스탭샷뿐만 아니라 각 파티션 최신 세그먼트의 메세지들 사용해서 복구됨

### 멱등적 프로듀서의 한계

- 카프카의 멱등적 프로듀서는 프로듀서의 내부 로직으로 인한 재시도가 발생할 경우 생기는 중복만을 방지
- 동일한 메세지를 가지고 producer.send()를 두 번 호출하면 멱등적 프로듀서 개입X 메세지 중복 발생

### 멱등적 프로듀서 사용법

- 프로듀서 설정에 enable.idempotence=true 설정
- 멱등적 프로듀서 사용시 변화하는 것들

## 2. 트랜잭션

- 카프카 스트림즈를 사용해서 개발된 애플리케이션에 정확성을 보장하기 위해 도입됨
- 스트림 처리 애플리케이션의 기본 패턴인 “읽기-처리-쓰기” 패턴에서 사용하도록 개발됨

### 트랜잭션 활용 사례

- 금융 애플리케이션
- 챗봇

### 트랜잭션이 해결하는 문제

- 애플리케이션 크래시로 인한 재처리
- 원본 클러스터로부터 메세지를 읽어서 처리 한 뒤
- 결과를 출력 토픽에 쓰고
- 읽어 온 메세지의 오프셋을 커밋
- 출력 토픽에는 이미 썼는데 입력 오프셋 커밋되기 전에 애플리케이션 크래시 발생
- 좀비 애플리케이션에 의해 발생하는 재처리
- 스스로 죽은 상태인지 모르는 컨슈머 = 좀비
- 좀비는 출력 토픽으로 데이터를 쓸 수 있음 → 중복된 결과 발생

### 트랜잭션은 어떻게 “정확히 한 번” 을 보장하는가?

- 원자적 다수 파티션 쓰기 atomic multipartition write 기능 도입
- 읽어온 이벤트의 오프셋을 커밋함과 동시에 두 개의 파티션에 원자적 다수 파티션 쓰기를 수행
- 이를 위해서는 트랜잭션적 프로듀서 사용 필요
- 보통 프로듀서와의 차이점: transactional.id 설정, initTransactions() 호출해 초기화
- 애플피케이션의 좀비 인스턴스가 중복 프로듀서 생성 방지 → 좀비 펜싱, 애플리케이션의 좀비 인스턴스가 출력 스트림에 결과를 쓰는 것을 방지
- 에포크 epoch 사용
- 트랜잭션 메타데이터에 컨슈머 그룹 메타데이터 추가 옵션
- isolation.level 설정값 → 트랜잭션 기능을 써서 쓰여진 메세지 읽어오는 방식 제어 가능
- read_uncommitted/read_committed

### 트랜잭션으로 해결할 수 없는 문제들

- 트랜잭션 기능 관련해서 자주하는 실수 두 가지
- “정확히 한 번 보장”이 카프카에 대한 쓰기 이외의 작동에서도 보장된다고 착각
- 컨슈머가 항상 전체 트랜잭션을 읽어온다고 가정하는 것
- 카프카의 트랜잭션 기능이 “정확히 한 번” 보장에 도움이 되지 않는 경우
- 스트림 처리에 있어서의 부수 효과
- 카프카 토픽에서 읽어서 데이터베이스에 쓰는 경우
- 하나의 트랜잭션에서 외부 데이터베이스에는 결과를 쓰고, 카프카에 오프셋 커밋해주는 매커니즘 X
- 데이터베이스에서 읽어서, 카프카에 쓰고, 여기서 다시 다른 데이터베이스에 쓰는 경우
- 종단 보장에 필요한 기능 X
- 한 클러스터에서 다른 클러스터로 데이터 복제
- 하나의 카프카 클러스터에서 다른 클러스터로 데이터 복사 시 “정확히 한 번 보장”
- 하지만, 트랜잭션의 원자성 보장 X
- 발행/구독 패턴
- read_committed 모드가 설정된 컨슈머들은 중단된 트랜잭션에 속한 레코드 보지 못함 → 오프셋 커밋 로직에 따라 메세지를 중복 처리 가능성 O

### 트랜잭션 사용법

- 일반적 방법: 카프카 스트림즈에서 exactly-once 보장 활성화
- 카프카 스트림즈를 사용하지 않는 방법: 트랜잭션 API를 직접 활용

### 트랜잭션 ID와 펜싱

- 트랜잭션 ID 선택: 중요, 조금 어려운 일
- 핵심 요구 조건
- 트랜잭션 ID가 동일 애플리케이션 인스턴시 재시작했을 때에는 일관적으로 유지
- 서로 다른 애플리케이션 인스턴스에 대해서는 서로 달라야함
- (브로커가 좀비 인스턴스의 요청을 처리하기 위해서)
- 펜싱 fencing 을 보장하는 방법
- (버전 2.5까지) 트랜잭션 ID를 파티션에 정적으로 대응시키는 것
- KIP-447: 트랜잭션 ID와 컨슈머 그룹 메타데이터를 함께 사용하는 펜싱 도입

### 트랜잭션의 작동 원리

- 기본적인 알고리즘: 찬디-램포트 스냅샷 알고리즘
- 현재 진행 중인 트랜잭션이 존재함을 로그에 기록. 연관된 파티션들도 함께 기록됨
- 로그에 커밋 혹은 중단 시도 기록
- 모든 파티션에 트랜잭션 마커를 씀
- 트랜잭션 종료되었음을 로그에 씀
- 트랜젹션 로그 필요

## 3. 트랜잭션 성능

- 트랜잭션은 프로듀서에 약간의 오버헤드 발생시킴
- 프로듀서에 있어서 트랜잭션 오버헤드는 트랜잭션에 포함된 메세지의 수와 무관
- 컨슈머의 경우, 커밋 마커를 읽어오는 작업에 관련해서 약간의 오버헤드
- 컨슈머는 아직 완료되지 않은 트랜잭션에 속하는 메세지들을 버퍼링할 필요가 없음

0 comments on commit 8b42613

Please sign in to comment.