아파치 카프카 애플리케이션 프로그래밍 with 자바

대충 쓰는 블로그·2022년 5월 15일
0
post-custom-banner

카프카 책

챕터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]
profile
일단 대충 쓰고 나중에 수습 하던지 말던지
post-custom-banner

0개의 댓글