카프카 책
챕터1
- 직렬화, 역직렬화를 통해 ByteArray로 통신, 자바 선언 모든 객체 지원
- 카프카는 상용 환경에서 최소 3대 이상의 서버에서 분산 운영함
- 프로듀서를 통해 전송받은 데이터를 안전하게 기록함
- 서버 3대 이상으로 이루어진 클러스터중 일부에서 장애가 발생하더라도 데이터를 지속적으로 복제함
- 데이터를 묶음 단위로 처리하는 배치 전송을 통해 낮은 지연과 높은 데이터 처리량을 가지게됨
- 네트워크 비용을 최대한 줄임, 묶음단위
- 스케일인아웃 용이, 브로커 개수
- 영속성, 디스크 기반이라 죽어도 괜춘, 페이지캐시 영역을 생성하여 사용, 처리량이 높음
- 고가용성, 여러브로커 분산복제, 최소 3대, 2대는 유실 가능성 복제 시간차이
* min.insync.replicas
챕터2
- 페이지 캐시로 시스템 메모리 사용, 힙메모리는 나머지 객체
* 이 특성으로 힙메모리를 5GB 이상으로 설정하지 않는것이 일반적
- 브로커 1G, 주키퍼 512MB 가 기본이라 1G 인스턴스에서는 메모리 오류 발생
* 실습에서는 힙메모리를 400mb 로 낮춤
- 백그라운드/포그라운드 실행 선택 가능
* 운영할때는 백그라운드가 일반적
- 주키퍼
클러스터 설정 리더 정보
컨트롤러 정보
* 상용환경에서는 3대 이상의 서버
토픽 생성
- 부트스트랩 서버
- 파티션 개수
- replicatio-factor : 브로커 갯수만큼 파티션 데이터 최대 복제 가능
- 파티션 개수, 데이터 리텐션 기간을 변경 할 수 있다
토픽 조회
[image:5A547065-EAAF-49FB-BD59-7C90D50DE9A3-39436-000021DFA9E5F39D/FCD6DF29-5355-465D-9574-4975CABF61F0.png]
Leader:0
은 3개의 파티션이 모두 Leader가 0으로 표시되어 있음을 뜻한다.
kafka-console-producer.sh
- 문자 작성후 엔터만하면 전송
- 주의 : ByteArraySerializer 로만 직렬화 된다
- 즉 String만 가능
- 기본 파티셔너
메세지 키가 널이면
라운드 로빈으로 파티션 전송
있으면
키의 해시값을 작성하여 존재하는 파티션중 한개에 할당
* 동일한 키는 동일한 파티션
kafka-console-consumer.sh
[image:F9E9E49A-4607-4113-B1AE-8EDD33C1A6BB-39436-000021E3ECC45A2D/B0F5E46F-2FC4-471A-B453-25EE34315E4D.png]
- group 옵션을 통해 새로운 컨슈머 그룹을 생성 함
- 데이터의 순서가 다를 것
모든 파티션으로부터 동일한 중요도로 데이터를 가져감
순서를 보장하고 싶으면 파티션 하나로 하셈
kafka-consumer-group.sh
- 컨슈머 그룹 리스트 확인 옵션ㄴ
- 컨슈머 그룹이 마지막으로 커밋한 토픽과 파티션 조회 가능
- 가장 최신 오프셋 조회 가능
- 랙 확인 가능
챕터 3
브로커
- 클라이언트와 데이터를 주고받기 위해 사용하는 주체
- 분산 저장, 장애에서 안전
- 1서버 1브로커
- 3개 이상의 브로커를 1개의 클러스터로 묶어서 운영
- 프로듀서가 요청한 파티션 -> 토픽의 파티션에 데이터를 저장
- 컨슈머가 데이터를 요청 -> 파티션에 저장된 데이터를 전달
저장, 전송
* 토픽이름 + 파티션번호 조합 -> 하위 디렉토리 생성
* 파티션이 11개면 11개의 디렉토리
* log에는 메시지와 메타데이터, index는 인덱싱한 정보
* 한번 읽은 내용은 페이지캐시를 사용, 디스크 속도 높임
복제, 싱크
- 데이터 복제는 fault tolerant system 원동력
- 브로커의 일부에 장애가 발생해도 안전하게
- 파티션의 복제 개수 설정 가능, 만약 3이라면? 아래 그림
[image:A9D97360-7C28-42C3-8AC6-B07C7341FD80-39436-0000222F1B397C11/AF7BAD17-1D24-4638-AFE6-4CD06B63F62F.png]
- 리더 파티션 : 프로듀서 또는 컨슈머와 직접 통신하는 파티션
- 팔로워 파티션 : 파티션의 팔로워
* 리더가 죽었을때 팔로워중 하나가 리더가됨
- 금융정보 같은건 데이터 복제 3
컨트롤러
- 다수 브로커중 한대가 컨트롤러 역할
- 다른 브로커들의 상태 체크, 브로커가 클러스터에서 빠지는 경우 리더 파티션 재분배
데이터 삭제
- 다른 메세징과 다름 : 컨슈머가 데이터를 가져가도 삭제 안됨
- 컨슈머나 프로듀서가 삭제 요청 불가
- 브로커만이 삭제 가능
- 파일단위로 삭제 가능 (로그 세그먼트)
- 세그먼트 파일 단위 기본값 1GB 파일, 조정 가능
오프셋 저장
- 컨슈머 그룹
파티션의 어느 레코드 까지 가져갔는지 오프셋을 커밋함
저장된 오프셋 -> 컨슈머 그룹은 다음 레코드부터 처리
코디네이터
- 다수 브로커중 한대는 코디네이터 역할
- 컨슈머그룹의 상태를 체크함
- 파티션을 컨슈머와 1:1 매칭되도록 분배함
- 컨슈머가 컨슈머 그룹에서 빠지면?
빵꾸난 파티션!
정상 동작하는 컨슈머로 할당
이 과정을 리밸런싱*
주키퍼
[image:0C384B07-15B6-4CB9-A369-848A35DBAC1D-39436-0000223F46F9DAF8/AD0A5BCD-5143-40C8-8DEB-000AC7ED3B44.png]
- 3개의 카프카 클러스터를 1개의 주키퍼에 연결
- 카프카 클러스터로 묶인 브로커들은 동일한 주키퍼 경로로 선언 해야함
토픽과 파티션
- 파티션
프로듀서가 보낸 데이터들이 들어가 저장
단위 : 레코드
병렬처리 핵심, 컨슈머들이 병렬 매칭됨
컨슈머 개수를 늘려 스케일 아웃
컨슈머 개수를 늘림과 동시에 파티션 개수를 늘리면 처리량 증가
FIFO 구조, pop은 되지 않음
- 작명 예시
* 한번 시작하면 까다로우니, 템플릿을 명확히 정해야 함
[image:20ACA0FA-6A16-42C1-A618-82BB522CB38B-39436-000022493ED042E1/5007A904-ED99-4147-82C5-D104AE6BAB87.png]
[image:2897CC23-BA4B-4CE8-A322-FF28CDE919D6-39436-0000224948FF2136/DC1FBD38-2D98-4CAD-993D-3B3831E90159.png]
레코드
- 타임스탬프, 메시지 키, 값, 오프셋 헤더로 구성
- 스키마 레지스트리로 관리해도 될듯
카프카 클라이언트
프로듀서, 컨슈머 API를 자바에서 사용
[image:0D2252A2-FCBE-4022-B2A2-888ACF83F4E9-39436-0000224B8B079FB1/E9314C7F-C6B0-4940-8948-3B7568FEB316.png]
프로듀서 API
- Properties 생성
* String 직렬화 클래스 StringSerializer 사용
- ProducerRecord 생성
메세지 키, 값 타입 제네릭 선언
record 를 파라미터로 가져가는 send 메서드 호출
즉각적 전송이 아님
프로듀서 내부에 가지고 있다가, 배치 형태로 묶어서 브로커에 전송한다
배치 전송이라고 부른다
flush 를 통해 프로듀서 내부 버퍼에 가지고 있던 레코드 배치를 브로커에 전송함
* 애플리케이션을 종료하기 전에 close 를 호출하여 안전하게 종료
- 파티셔너
UniformSticyPartitioner (기본)
라운드로빈 단점 해결
배치로 모두 묶일때 까지 기다렸다가, 모두 동일한 파티션에 전송, 성능 향상
RoundRobinPartitioner
들어오는 대로 파티션을 순회 전송, 배치 빈도 적음
공통 : 메시지 키의 해시값과 파티션을 매칭하여 데이터를 전송함
필수옵션
- 브로커 묶음
- 키 직렬화 클래스
- 값 직렬화 클래스
선택옵션
- acks
0 전송 즉시 성공
1 리더 파티션에 저장되면 성공
* -1 리더, 팔로워 파티션에 저장되면 성공
- 버퍼 메모리
* 배치 메모리 단위
- 리트라이
* 에러를 받고 재전송 시도 횟수
- 배치 사이즈
* 배치 최대 용량
- 배치 전송 최소 시간
- 파티셔너 클래스
- 멱등성 동작 여부
- 트랙잭션 단위 여부
정상 전송 여부 확인
- Future 로 된 send 결과값을 받아서 확인 가능
- 동기로 결과를 받거나 (성능 이슈) 비동기로 oncomplete 결과를 받거나
컨슈머 API
- 기본 설정 : 오토커밋 컨슈머 어플리케이션
- 무한루프, poll 호출하여 데이터를 가져와서 처리
컨슈머 중요 개념
운영 방법 2가지
-
1개 이상의 컨슈머로 이루어진 컨슈머 그룹 운영
* 컨슈머 1개로 이루어진 컨슈머 그룹, 파티션 3개 할당
[image:6D69EEBC-8E36-4FA2-92F9-D4360A05A15D-39429-00002275599F4951/69E9570E-A509-4C75-81E0-D3608154CED1.png]
* 1개의 파티션은 최대 1개의 컨슈머만 할당 가능
* 컨슈머 그룹의 컨슈머 개수는, 토픽의 파티션 개수보다 같거나 작아야 한다
* 컨슈머 2개, 파티션 3개라면?
[image:4EFCBD01-6FBF-4D47-B3ED-813D97A125AF-39429-00002277B8F3FFF4/B6897A6F-0F6F-4FE8-897D-76B33BF1CC3C.png]
-
토픽의 특정 파티션만 구독하는 컨슈머 운영
리밸런싱
- 컨슈머가 추가되는 상황
- 컨슈머가 제외되는 상황
- 컨슈머중 1개에 이슈가 발생한다면
해당 파티션은 데이터 처리를 하지 못하고 있으므로, 지연이 발생
컨슈머를 컨슈머 그룹에서 자동 제외
- 자주 일어나선 안된다
파티션의 소유권을 컨슈머로 재할당하는 과정
컨슈머 그룹의 컨슈머들이 토픽의 데이터를 읽을 수 없음
- 그룹 조정자는 리밸런싱을 발동, 삭제추가 감지 브로커중 한대가 수행
- 어디까지 가져갔는지 커밋을 통해 기록함
- 내부 컨슈머 토픽에 기록함
- 중복발생!
어느레코드까지 읽어갔는지 기록되지 못했다면?
중복이 발생 할 수 있음
- 중복이 안되려면?
* 컨슈머 애플리케이션 단 -> 오프셋 커밋을 정상적으로 처리했는지 검증 해야함
- 오프셋 커밋
비명시적
오토커밋(기본)
auto.commint.interval.ms 시점까지 읽은 레코드의 오프셋을 커밋
리밸런싱 또는 컨슈머 강제종료 상황
컨슈머가 처리하는 데이터가 중복 또는 유실 될 수 있는 가능성
중복이나 유실을 허용하지 않으려면 자동 커밋 절대 안됨
명시적
poll 호출 이후 반환받은 데이터의 처리가 완료되고 commitsync 메서드 호출
필수옵션
- 브로커셋
- 역직렬화 키 클래스
- 역직렬화 값 클래스
선택옵션
- 그룹 아이디
- 파티션을 읽을때 컨슈머 오프셋이 없는 경우 어느 오프셋부터 읽을지
latest
earlisest
* none
- 오토커밋 여부
- 오토커밋 간격
- 반환되는 레코드 개수 지정
- 컨슈머 세션 타임아웃
* 보통 하트비트 시간간격의 3배
- poll 메서드 호출 간격 최대 시간
* 너무 시간이 많이 걸리면 비정상으로 판단하기, 기본값 5분
- 아이솔레이션 레벨
프로듀서가 트랜잭션 단위로 보낼 경우
커밋이 완료된 레코드만 읽는다.. 커밋여부 관련 없이 읽는다.. 가 있네
리밸런스 리스너를 가진 컨슈머
- poll 메서드 처리중에 리밸런싱 되면?
- 커밋되지 않은걸로 감지, 중복 처리 될수 있음
챕터 4 : 카프카 상세 개념 설명
토픽과 파티션
적정 파티션 개수
고려할점 3가지
- 데이터 처리량
- 메시지 키 사용 여부
- 브로커, 컨슈머 영향도
프로듀서가 보내는 데이터양으로 정하면 된다.
프로듀서가 보내는 데이터가 1000 레코드라면?
컨슈머 처리 성능이 100 이라면 필요한 파티션 개수는 10개
[image:380A9F83-A6B5-4E05-A17A-FF2EA8E50A06-39429-0000228CF82D22F6/387160A9-833A-4B76-A42F-9C96FC02DB8F.png]
-
무조건 실시간으로 처리 되어야 한다? -> 최대치로 잡고함
* 그럴필요 없으면 peek 가 아닐때
-
개수를 늘리는게 무조건 능사는 아님, 컨슈머, 브로커에 부담이 간다
-
순서가 보장되어야 한다면
* 파티션의 변화 없는 방향으로 운영, 넉넉하게 잡고 생성
-
순서를 지키지 않아도 된다면
* 넉넉하게 잡지 않아도 됨, 데이터 양에 따라 늘리면 됨
-
파티션은 각 브로커의 파일 시스템을 사용함
-
파티션이 늘어나는 만큼, 브로커에서 접근하는 파일 개수가 많아짐
-
운영체제 에서는 프로세스당 열수 있는 최대 파일 개수 제한됨
-
안정적으로 유지하기 위해선, 각 브로커당 파티션 개수를 모니터링 해야함
-
브로커당 파티션 개수를 확인하고 늘리셈 늘리기전에
-
파티션 개수가 너무 많다면 파티션 개수를 분산하기 위해서 브로커 개수를 늘리는 방안도 같이 고려해야 함
토픽 정리 정책
복제 개수 3, 최소 복제 개수 3이면 1대만 이슈가 발생하면 동작하지 못함, 2가 적당할 듯
절대로 브로커 개수와 동일하게 설정 하지 말라
멱등성 프로듀서
- 기본 동작 방식은 적어도 한번 전달 at least once 지원
- 두번이상 적재할 가능성이 있음, 중복 발생
- 정확히 한번 전달을 지원함
- 멱등성 프로듀서는 기본과 다르게 프로듀서 PID와 시퀀스넘버를 함께 전달함
- 동일한 메시지의 적재 요청이 오더라도 단 한번만 데이터를 적재함
- 단, 동일한 세션에서만 정확히 한번 보장 ( PID의 생명주기)
- 프로듀서 이슈가 발생하여 종료되고, 애플리케이션이 재시작되면 PID가 달라짐, 보장 X
- acks 가 자동으로 all로 바뀜 retries 는 max 로 바뀜
- 원리
프로듀서가 여러번 전송하되, 브로커가 여러번 전송된 데이터를 확인함
중복된 데이터는 적재하지 않는 것
트랜잭션 프로듀서
- 다수의 파티션에 데이터를 저장할때, 모든 데이터에 대해 동일한 원자성을 만족시키기 위해
- 다수의 데이터를 동일한 트랜잭션으로 묶음으로써 전체 데이터를 처리하거나 아니거나 하게끔
- 컨슈머는 기본적으로 파티션에 쌓이는 대로 모두 가져가서 처리됨
- 트랜잭션으로 묶인 데이터를 브로커에서 가져갈때는 다르게 설정 가능
컨슈머 배포
- 중단 배포
컨슈머 랙이 늘어남
신규로직 적용 전후의 데이터 명확히 구분 가능
- 무중단 배포
블루그린 배포
새로 배포되면 쉬는 상태다가, 기존꺼 죽으면 교체됨
리밸런싱 한번, 짧게 발생됨
대신 개수가 같아야함
[image:D5B36A91-D4C0-415D-91A7-AFE9CA729F71-39429-000022BB0326CDEA/72295860-F3F7-42F9-B9FE-13F9CB805480.png]