kafka를 왜 사용하는가?
이벤트 드리븐 아키텍처를 구현하는데에 동기방식으로 구현할 경우 다음과 같은 한계에 봉착하게 된다.
- 여러 네트워크를 이용하는 환경에서 모든 데이터 변경에 대한 올바른 전달 보장 문제
- 동일한 데이터를 동시에 수정하면서 정확하게 순서를 보장해야 하는 문제, 그리고 수정된 이벤트들을 정확한 순서대로 아웃바운드 전송하는 문제
- 다양한 클라이언트들의 요구사항을 효율적으로 지원하기 어려운 문제
- 빠른 전송을 위한 클라이언트 또는 대량의 배치 전송을 위한 클라이언트를 지원하기 어려운 문제
이를 해결하는 요소는 다음과 같다. 그리고 kafka가 이 요소를 갖고 있다.
- 비동기 방식의 스트리밍 플랫폼
- 빠른 데이터 수집이 가능한 높은 처리량
- 순서 보장
- 적어도 한번 전송방식으로 누락이 없음
- 멱등성
- 클라이언트의 풀링방식 데이터 소비
- 강력한 파티셔닝으로 수평확장 용이
Kafka 구성요소
- 주키퍼(ZooKeeper) : 카프카의 메타데이터 관리 및 브로커의 정상상태 점검을 담당
- 카프카(Kafka) 또는 카프카 클러스터 : 여러대의 브로커를 구성한 클러스터를 의미
- 브로커(Broker) : 카프카 애플리케이션이 설치된 서버 또는 노드를 말한다.
- 프로듀서(Producer) : 카프카로 메시지를 보내는 역할을 하는 클라이언트 총칭
- 컨슈머(Consumer) : 카프카에서 메시지를 꺼내가는 역할을 하는 클라이언트 총칭
- 토픽(Topic) : 카프카는 메시지 피드들을 토픽으로 구분하고, 각 토픽의 이름은 카프카 내에서 고유
- 파티션(Partition) : 병렬처리 및 고성능을 억기위해 하나의 토픽을 여러개로 나눈것을 의미
- 세그먼트(Segment) : 프로듀서가 전송한 실제 메시지가 브로커의 로컬 디스크에 저장되는 파일
- 메시지(Message) 또는 레코드(Record) : 프로듀서가 브로커로 전송하거나 컨슈머가 읽어가는 데이터 조각을 의미
리플리케이션
kafka에서 리플리케이션이란 각 메시지들을 여러개로 복제해서 카프카 클러스터내 브로커들에 분산시키는 동작을 의미합니다. 이러한 리플리케이션 동작 덕분에 하나의 브로커가 종료되더라도 카프카는 안정성을 유지할 수 있습니다.
Topic을 만들때 '--replication-factor 3' 이라는 옵션을 주게 되면 원본을 포함한 리플리케이션이 총 3개가 있다는 뜻힙니다.
# ./kafka-topics.sh --bootstrap-server localhost:9092 --create --topic peter-overview01 --partitions 1 --replication-factor 3
Topic이 리플리케이션 되는 것이 아니라 Partition이 Replication되는 것입니다. 리플리케이션 팩터 수가 커지면 안정성은 높아지지만 그만큼 브로커 리소스를 많이 사용하게 됩니다. 따라서 복제에 대한 오버헤드를 줄여서 최대한 브로커를 효율적으로 사용하는 것을 권장합니다.
- 테스트나 개발환경 : 리플리케이션 팩터 수를 1로 설정
- 운영환경(로그성 메시지로서 약간의 유실 허용) : 리플리케이션 팩터 수를 2로 설정
- 운영환경*유실 허용하지 않음) : 리플리케이션 팩터 수를 3으로 설정
파티션
하나의 토픽이 한번에 처리할 수 있는 한계를 높이기 위해 토픽 하나를 여러개로 나뉜 병렬처리가 가능하게 만든것을 파티션 이라고 합니다. 이렇게 하나를 여러개로 나누면 분산처리도 가능합니다. 이렇게 나누니 파티션 수만큼 컨슈머를 연결할 수 있습니다.(Partition >= Consumer). 토픽을 생성할때 파티션 수도 옵션으로 설정합니다.
주의할 점은 파티션 수는 초기생성후 언제든지 늘릴수 있지만, 반대로 한번 늘린 파티션 수는 절대로 줄일 수 없다는 것입니다. 따라서 초기에는 파티션수를 작게 생성한 후 메시지 처리량이나 컨슈머의 LAG등을 모니터링 하면서 조금씩 늘려가는 방법이 가장 좋습니다. 여기서 컨슈머의 LAG이란 '프로듀서가 보낸 메시지 수 - 컨슈머가 가져간 메시지 수'를 나타냅니다.
세그먼트
프로듀서를 이용해 보낸 메시지는 바로 해당 토픽의 파티션에 저장되어 있습니다. 이처럼 프로듀서에 의해 브로커로 전송된 메시지는 토픽의 파티션에 저장되며, 각 메시지들은 세그먼트라는 로그 파일의 형태로 브로커의 로컬 디스크에 저장됩니다.
kafka의 핵심개념
분산 시스템
분산시스템은 네트워크 상에서 연결된 컴퓨터들의 그룹을 말하며, 단일 시스템이 갖지 못한 높은 성능을 목표로 합니다. 이러한 분산시스템은 성능이 높다는 장점 이외에도 하나의 서버 또는 노드등에 장애가 발생할 때 다른 서버 또는 노드가 대신 처리하므로 장애 대응이 탁우러하며, 부하가 높은 경우에는 시스템 확장이 용이하다는 장점도 있습니다. 카프카도 분산 시스템이므로 최초 구성한 클러스터의 리소스가 한계치에 도달해 더욱 높은 메시지 처리량이 필요한 경우, 브로커를 추가하는 방식으로 확장이 가능합니다. 카프카에서 브로커는 온라인 상태에서 매우 간단하게 추가할 수 있습니다.
페이지 캐시
카프카는 높은 처리량을 얻기위해 몇가지 기능을 추가했는데, 그중 대표적인 것이 바로 페이지 캐시의 이용입니다. 운영체제는 성능을 높이기 위해 꾸준히 진화하고 개선되고 있는데, 특히 페이지 캐시의 활용이 대표적입니다. 카프카 역시 OS의 페이지 캐시를 활용하는 방식으로 설계되어 있습니다. 페이지 캐시는 직접 디스크에 읽고 쓰는 대신 물리 메모리중 애플리케이션이 사용하지 않는 일부 잔여 메모리를 활용합니다. 이렇게 페이지 캐시를 이용하면 디스크 I/O에 대한 접근이 줄어드므로 성능을 높일 수 있습니다.
배치 전송 처리
카프카는 프로듀서 컨슈머 클라이언트들과 서로 통신하며 이들 사이에서 수많은 메시지를 주고 받습니다. 이 때 발생하는 수많은 통신을 묶어서 처리할 수 있다면, 단건으로 통신할 때에 비해 네트워크 오버헤드를 줄일 수 있을 뿐만아니라 장기적으로는 더욱 빠르고 효율적으로 처리할 수 있습니다.
압축전송
카프카는 메시지 전송 시 좀더 성능이 높은 압축 전송을 사용하는 것을 권장합니다. 카프카에서 지원하는 압축 타입은 gzip, snappy, lz4, zstd등입니다. 압축만으로도 네트워크 대역폭이나 회선 비용들을 줄일 수 있는데, 앞서 설명한 배치 전송과 결합해 사용한다면 더욱 높은 효과를 얻게 됩니다. 파일 하나를 압축하는 것보다 비슷한 파일 10개, 혹은 20개를 압축하는 것이 더욱 좋기 때문입니다. 높은 압축률이 필요한 경우에 gzip, zstd를 권장하고 빠른 응답 속도가 필요하다면 lz4나 snappy를 권장합니다.
토픽, 파티션, 오프셋
카프카는 토픽이라는 곳에 데이터를 저장하는데 이는 우리가 흔히 사용하는 메일 전송 시스템에서 이메일 주소 정도의 개념으로 이해하면 쉽습니다. 토픽은 병렬 처리를 위해 여러 개의 파티션이라는 단위로 다시 나뉩니다. 토픽은 병렬 처리를 위해 여러개의 파티션이라는 단위로 다시 나뉩니다 카프카에서는 이와 같은 파티셔닝을 통해 단 하나의 토픽이라도 높은 처리량을 수행할 수 있습니다. 이 파티션의 메시지가 저장되는 위치를 오프셋이라고 부르며 오프셋은 순차적으로 증가하는 숫자 형태로 되어 있습니다.
고가용성 보장
카프카는 앞서 설명한 것처럼 분산 시스템이기 때문에 하나의 서버나 노드가 다운되어도 다른 서버 또는 노드가 장애가 발생한 서버의 역할을 대신해 안정적인 서비스가 가능합니다. 이러한 고가용성을 보장하기 위해 카프카에서는 리플리케이션 기능을 제공합니다. 토픽을 생성할 때 옵션으로 리플리케이션 팩터 수를 지정할 수 있으며, 이 숫자에 따라 리플리케이션 들이 존재하게 됩니다. 원본과 리플리케이션을 구분하기 위해 리더, 팔로워 라고 부릅니다.
리플리케이션 수 | 리더 수 | 팔로워 수 |
2 | 1 | 1 |
3 | 1 | 2 |
4 | 1 | 3 |
위 표는 리플리케이션 팩터 수에 따른 리더와 팔로워 수의 관계를 보여줍니다. 이 표에서 보는 바와 같이 리더의 숫자는 1을 유지한 채 리플리케이션 팩터 수에 따라 팔로워 수만 증가하게 됩니다. 하지만 팔로워 수가 많다고 딱히 좋은것은 아닙니다. 팔로워의 수만큼 결국 브로커의 디스크 공간도 소비되므로 이상적인 리플리케이션 팩터 수를 유지해야 하며, 따라서 일반적으로 카프카에서는 리플리케이션 팩터 수를 3으로 구성하도록 권장합니다.
주키퍼의 의존성
카프카를 언급하면서 빼놓을 수 없는것이 주키퍼 입니다. 앞에서도 이미 여러번 간략히 언급한 바 있는 주키퍼는 하둡의 서브 프로젝트 중 하나로 출발해 2011년 아파치의 탑레벨 프로젝트로 승격됐습니다. 오늘날에 이르러 카프카를 비롤해 아파치 산하 프로젝트인 Hadoop, NiFi, HBase 등 많은 분산 애플리케이션에서 코디네이터 역할을 하는 애플리케이션으로 사용되고 있습니다. 주키퍼는 여러대의 서버를 앙상을로 구성하고 살아있는 노드수가 과반수 이상유지된다면 지속적인 서비스가 가능한 구조입니다. 따라서 주키퍼는 반드시 홀수로 구성해야 합니다. 하지만 최근 들어 카프카가 점점 성장하면서 주키퍼 성능의 한계가 드러나기 시작했고 주키퍼의 한계에서 벗어나고자 카프카에서 주키퍼에 대한 의존성을 제거하려는 움직임이 한참 진행중입니다. 22년초 물벼에는 주키퍼가 삭제된 카프카 버전이 릴리즈될 예정입니다.
'PaaS > MQ' 카테고리의 다른 글
kafka consumer의 내부 동작 원리와 구현 (0) | 2022.06.22 |
---|---|
kafka producer의 내부 동작 원리와 구현 (0) | 2022.06.14 |
kafka 리플리케이션, 컨트롤러, 로그 (0) | 2022.06.14 |
kafka 프로듀서, 컨슈머 개념과 사용법 (0) | 2022.06.13 |
kafka 서버 설치하기 (0) | 2022.06.07 |